#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "DiskImage.h"

#define ERR_OPEN        "Error: can't open source file"
#define ERR_GETLEN      "Error: can't get file length!"
#define ERR_NOMEM       "Error: no memory!"
#define ERR_FORMAT      "Error: incorrect format"
#define ERR_FILEVER     "Error: unknown version of"
#define ERR_FILECRC     "Error: bad file CRC"
#define ERR_CANTWRITE   "Error: write to file failed!"
#define ERR_UNKFORMAT   "Error: Unknown format of source file!"
#define ERR_MANYCYLS    "Error: out of 256 cylinders in opening source file!"
#define ERR_MANYSIDS    "Error: out of 2 surfaces in opening source file!"
#define ERR_IMPOSSIBLE  "Error: impossible format in opening source file!"
#define ERR_CORRUPT     "Error: source file is corrupted!"
#define ERR_TD0DOSALLOC "Error: files TD0 in 'DOS Allocated sectors were copied' format not supported!"

#define STR_CREATEDISKNAME "MiSTer    "

char errsect[] = "ERROR: THIS SECTOR NOT FOUND OR IN NON TR-DOS FORMAT!";

enum TDiskImageType { DIT_UNK, DIT_SCL, DIT_FDI, DIT_TD0, DIT_UDI, DIT_HOB, DIT_FDD };

struct VGFIND_TRACK
{
	unsigned char *TrackPointer;
	unsigned char *ClkPointer;
	unsigned int TrackLength;
	bool FoundTrack;
};


struct VGFIND_ADM
{
	unsigned char* TrackPointer;
	unsigned char* ClkPointer;
	unsigned int TrackLength;

	unsigned char *ADMPointer;
	unsigned int ADMLength;

	unsigned int MarkedOffsetADM;
	unsigned int OffsetADM;
	unsigned int OffsetEndADM;
	bool FoundADM;
	bool CRCOK;
};


struct VGFIND_SECTOR
{
	VGFIND_ADM vgfa;

	unsigned char *SectorPointer;
	unsigned int SectorLength;

	unsigned int MarkedOffsetSector;
	unsigned int OffsetSector;
	unsigned int OffsetEndSector;
	bool FoundDATA;
	bool CRCOK;
	unsigned char DataMarker;
};


class TDiskImage
{
	unsigned int FTrackLength[256][256];
	unsigned char* FTracksPtr[256][256][2];

	TDiskImageType FType;

	unsigned short MakeVGCRC(unsigned char *data, unsigned long length);
public:
	bool Changed;

	bool ReadOnly;
	bool DiskPresent;
	unsigned char MaxTrack;
	unsigned char MaxSide;

	TDiskImage();
	~TDiskImage();

	bool FindTrack(unsigned char CYL, unsigned char SIDE, VGFIND_TRACK *vgft);
	bool FindADMark(unsigned char CYL, unsigned char SIDE,
		unsigned int FromOffset,
		VGFIND_ADM *vgfa);
	bool FindSector(unsigned char CYL, unsigned char SIDE,
		unsigned char SECT,
		VGFIND_SECTOR *vgfs, unsigned int FromOffset = 0);
	void ApplySectorCRC(VGFIND_SECTOR vgfs);


	void Open(const char *filename, bool ReadOnly);

	void writeTRD(fileTYPE *hfile);

	void readSCL(int hfile, bool readonly);
	void readFDI(int hfile, bool readonly);
	void readUDI(int hfile, bool readonly);
	void readTD0(int hfile, bool readonly);
	void readFDD(int hfile, bool readonly);
	void readHOB(int hfile);

	void formatTRDOS(unsigned int tracks, unsigned int sides);

	void ShowError(const char *str);
};

#pragma pack(1)
struct UDI_HEADER               // 16 bytes
{
	unsigned char ID[4];
	unsigned long UnpackedLength;
	unsigned char Version;
	unsigned char MaxCylinder;
	unsigned char MaxSide;
	unsigned char _zero;
	unsigned long ExtHdrLength;
};

struct TD0_MAIN_HEADER          // 12 bytes
{
	char ID[2];                  // +0:  "TD" - 'Normal'; "td" - packed LZH ('New Advanced data compression')
	unsigned char __t;           // +2:  = 0x00
	unsigned char __1;           // +3:  ???
	unsigned char Ver;           // +4:  Source version  (1.0 -> 10, ..., 2.1 -> 21)
	unsigned char __2;           // +5:  ???
	unsigned char DiskType;      // +6:  Source disk type
	unsigned char Info;          // +7:  D7-наличие image info
	unsigned char DataDOS;       // +8:  if(=0)'All sectors were copied', else'DOS Allocated sectors were copied'
	unsigned char ChkdSides;     // +9:  if(=1)'One side was checked', else'Both sides were checked'
	unsigned short CRC;          // +A:  CRC хидера TD0_MAIN_HEADER (кроме байт с CRC)
};

struct TD0_INFO_DATA             // 10 байт без строки коментария...
{
	unsigned short CRC;          // +0:  CRC для структуры COMMENT_DATA (без байтов CRC)
	unsigned short strLen;       // +2:  Длина строки коментария
	unsigned char Year;          // +4:  Дата создания - год (1900 + X)
	unsigned char Month;         // +5:  Дата создания - месяц (Январь=0, Февраль=1,...)
	unsigned char Day;           // +6:  Дата создания - число
	unsigned char Hours;         // +7:  Время создания - часы
	unsigned char Minutes;       // +8:  Время создания - минуты
	unsigned char Seconds;       // +9:  Время создания - секунды
};

struct TD0_TRACK_HEADER         // 4 bytes
{
	unsigned char SectorCount;
	unsigned char Track;
	unsigned char Side;
	unsigned char CRCL;
};

struct TD0_SECT_HEADER          // 8 bytes
{
	unsigned char ADRM[6];
	unsigned short DataLength;
};

struct FDD_MAIN_HEADER
{
	char ID[30];                /* сигнатура */
	unsigned char MaxTracks;    /* число треков (цилиндров) */
	unsigned char MaxHeads;     /* число головок (1 или 2) */
	long diskIndex;             /* unused */
	long DataOffset[512 * 2];     /* смещение в файле к структурам заголовков */
								/* треков       */
};

struct FDD_TRACK_HEADER
{
	unsigned char trkType;      /* unused */
	unsigned char SectNum;      /* число секторов на треке */
	struct
	{
		/* заголовок сектора */
		unsigned char trk;     /* номер трека */
		unsigned char side;    /* номер стороны */
							   /* 7 бит этого байта указывает бит a */
		unsigned char sect;    /* номер сектора */
		unsigned char size;    /* размер сектора (код) */
		long SectPos;          /* смещение в файле к данным сектора */
	} sect[256];
};


struct TRDOS_DIR_ELEMENT        // 16 bytes
{
	char FileName[8];
	char Type;
	unsigned short Start;
	unsigned short Length;
	unsigned char SecLen;
	unsigned char FirstSec;
	unsigned char FirstTrk;
};
#pragma pack()

static const unsigned char sbootimage[] = {
	0x00, 0x01, 0x1a, 0x00, 0xf9, 0xc0, 0xb0, 0x22, 0x31, 0x35, 0x36, 0x31, 0x39, 0x22, 0x3a, 0xea,
	0x3a, 0xf7, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x20, 0x0d, 0x00, 0x02,
	0x0f, 0x00, 0xf9, 0xc0, 0xb0, 0x22, 0x31, 0x35, 0x36, 0x31, 0x39, 0x22, 0x3a, 0xea, 0x3a, 0xf7,
	0x0d, 0x00, 0x03, 0x0b, 0x00, 0xf9, 0xc0, 0xb0, 0x22, 0x31, 0x35, 0x36, 0x31, 0x36, 0x22, 0x0d,
	0x00, 0x04, 0x47, 0x00, 0xea, 0x21, 0xa8, 0x61, 0x11, 0xa9, 0x61, 0x01, 0x07, 0x9d, 0x36, 0x00,
	0xed, 0xb0, 0x21, 0xa8, 0x61, 0xed, 0x5b, 0xf4, 0x5c, 0x01, 0x05, 0x0f, 0xcd, 0x13, 0x3d, 0x21,
	0x00, 0xa6, 0xed, 0x5b, 0xf4, 0x5c, 0x01, 0x05, 0x08, 0xcd, 0x13, 0x3d, 0x21, 0x50, 0xeb, 0xed,
	0x5b, 0xf4, 0x5c, 0x01, 0x05, 0x0d, 0xcd, 0x13, 0x3d, 0xcd, 0xa8, 0x61, 0x21, 0xa8, 0x61, 0x11,
	0xa9, 0x61, 0x01, 0x07, 0x9d, 0x36, 0x00, 0xed, 0xb0, 0xc9, 0x0d, 0x00, 0x0a, 0x25, 0x00, 0xe7,
	0xc3, 0xa7, 0x3a, 0xda, 0xc3, 0xa7, 0x3a, 0xd9, 0xb0, 0x22, 0x37, 0x22, 0x3a, 0xfd, 0xb0, 0x22,
	0x36, 0x35, 0x33, 0x34, 0x37, 0x22, 0x3a, 0xf9, 0xc0, 0xb0, 0x22, 0x32, 0x33, 0x39, 0x33, 0x36,
	0x22, 0x3a, 0xf7, 0x0d, 0x80, 0xaa, 0x0a, 0x00, 0x6f, 0x6f, 0x74, 0x31, 0x31, 0x22, 0xca, 0x31,
	0x30, 0x0d, 0x80, 0x31, 0x35, 0x36, 0x31, 0x36, 0x0e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x0d, 0x80,
	0xca, 0xf3, 0x5e, 0x06, 0x00, 0x00, 0x00, 0xf3, 0x5e, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0xfd, 0x22, 0xc8, 0xaf, 0xd9, 0x22, 0xca, 0xaf, 0xed, 0x73, 0xcc, 0xaf, 0xed, 0x57, 0x32, 0xce,
	0xaf, 0x11, 0x00, 0x00, 0x21, 0x00, 0x9d, 0x01, 0x05, 0x08, 0xcd, 0x13, 0x3d, 0x31, 0x68, 0xbf,
	0xf3, 0x21, 0x00, 0xfd, 0x11, 0x01, 0xfd, 0x01, 0x00, 0x01, 0x36, 0xfc, 0xed, 0xb0, 0x21, 0x5a,
	0x67, 0x22, 0xfd, 0xfc, 0x3e, 0xc3, 0x32, 0xfc, 0xfc, 0xed, 0x5e, 0x3e, 0xfd, 0xed, 0x47, 0xcd,
	0x53, 0xeb, 0xcd, 0x50, 0xeb, 0xcd, 0x13, 0x65, 0xfb, 0x21, 0x9b, 0x6e, 0x11, 0x00, 0x77, 0x01,
	0xc8, 0x00, 0xed, 0xb0, 0x21, 0x77, 0x6b, 0x11, 0x00, 0x76, 0x0e, 0x28, 0xed, 0xb0, 0x21, 0x9f,
	0x6b, 0x11, 0x5c, 0x76, 0x0e, 0x09, 0xed, 0xb0, 0x11, 0x00, 0x78, 0x3e, 0x40, 0x32, 0x8e, 0x76,
	0xcd, 0xf4, 0x62, 0x21, 0x00, 0x78, 0x11, 0x00, 0x81, 0x06, 0x08, 0xc5, 0xcd, 0xd9, 0x63, 0x24,
	0x14, 0xc1, 0x10, 0xf7, 0x21, 0x00, 0x77, 0xcd, 0x25, 0x64, 0xcd, 0x25, 0x64, 0xcd, 0x25, 0x64,
	0x11, 0x00, 0x8a, 0x3e, 0x80, 0x32, 0x8e, 0x76, 0xcd, 0xf4, 0x62, 0x21, 0x00, 0x8a, 0x11, 0x00,
	0x93, 0x06, 0x08, 0xc5, 0xcd, 0xd9, 0x63, 0x24, 0x14, 0xc1, 0x10, 0xf7, 0x06, 0x11, 0x21, 0x00,
	0x8a, 0xc5, 0xcd, 0x25, 0x64, 0x24, 0xc1, 0x10, 0xf8, 0xcd, 0xc9, 0x6d, 0x3e, 0xff, 0x32, 0xb0,
	0xb3, 0x3c, 0x32, 0xb1, 0xb3, 0x3e, 0x05, 0x32, 0xb2, 0xb3, 0x3e, 0x08, 0x32, 0xb3, 0xb3, 0x3e,
	0x0e, 0x32, 0xb4, 0xb3, 0xcd, 0x61, 0x64, 0x3a, 0xb0, 0xb3, 0x3c, 0x32, 0xb0, 0xb3, 0x3a, 0xb0,
	0xb3, 0xe6, 0x01, 0xfe, 0x01, 0x20, 0x18, 0x21, 0x84, 0xac, 0x22, 0x87, 0x64, 0xcd, 0x85, 0x64,
	0xcd, 0x85, 0x64, 0x21, 0xfc, 0xac, 0x22, 0x87, 0x64, 0xcd, 0x85, 0x64, 0xcd, 0x85, 0x64, 0x3a,
	0xb0, 0xb3, 0xe6, 0x03, 0xfe, 0x03, 0x20, 0x21, 0x21, 0x00, 0x40, 0x11, 0x00, 0x78, 0x01, 0xb1,
	0xb3, 0xcd, 0xdd, 0x64, 0x21, 0x1b, 0x40, 0x11, 0x00, 0x8a, 0x01, 0xb2, 0xb3, 0xcd, 0xdd, 0x64,
	0x21, 0x74, 0xad, 0x22, 0x87, 0x64, 0xcd, 0x85, 0x64, 0x3a, 0xb0, 0xb3, 0xe6, 0x07, 0xfe, 0x07,
	0x20, 0xa5, 0x21, 0x60, 0x50, 0x11, 0x00, 0x8a, 0x01, 0xb3, 0xb3, 0xcd, 0xdd, 0x64, 0x21, 0x7b,
	0x50, 0x11, 0x00, 0x78, 0x01, 0xb4, 0xb3, 0xcd, 0xdd, 0x64, 0x18, 0x8b, 0xfd, 0x21, 0x5c, 0x76,
	0x0e, 0x08, 0x21, 0x00, 0x77, 0x06, 0x28, 0xdd, 0x21, 0x00, 0x76, 0xcd, 0x3e, 0x63, 0xc5, 0x06,
	0x05, 0xdd, 0x7e, 0x00, 0xe6, 0x3f, 0xcd, 0x57, 0x63, 0xdd, 0x2c, 0x10, 0xf4, 0x0d, 0x20, 0xef,
	0xc1, 0xcd, 0x67, 0x63, 0x10, 0xe1, 0x14, 0x1e, 0x00, 0x0d, 0x20, 0xd6, 0xeb, 0x11, 0x00, 0x76,
	0x3a, 0x8e, 0x76, 0x47, 0x2c, 0x2c, 0x1a, 0xb8, 0x38, 0x02, 0x36, 0x18, 0x2c, 0x2c, 0x2c, 0x1c,
	0x7d, 0xfe, 0xc8, 0x20, 0xef, 0xc9, 0xd9, 0x21, 0x98, 0x76, 0x11, 0x99, 0x76, 0x01, 0x27, 0x00,
	0x70, 0xed, 0xb0, 0xd9, 0x79, 0x32, 0x52, 0x63, 0xfd, 0x7e, 0x00, 0x32, 0xc0, 0x76, 0xc9, 0xdd,
	0xe5, 0xdd, 0x21, 0x98, 0x76, 0x32, 0x62, 0x63, 0xdd, 0x36, 0x00, 0x01, 0xdd, 0xe1, 0xc9, 0xc5,
	0xfd, 0xe5, 0xd5, 0xe5, 0xdd, 0xe1, 0xe5, 0x3a, 0xc0, 0x76, 0xe6, 0xf8, 0x0f, 0x0f, 0x0f, 0x4f,
	0x06, 0x00, 0xeb, 0x09, 0xe5, 0xfd, 0xe1, 0x21, 0x98, 0x76, 0x3a, 0xc0, 0x76, 0xe6, 0x07, 0x4f,
	0x3e, 0x07, 0x91, 0x4f, 0x16, 0x05, 0x1e, 0x7e, 0x7b, 0x32, 0x98, 0x63, 0xaf, 0xdd, 0xcb, 0x00,
	0x46, 0x28, 0x02, 0x3e, 0x40, 0x08, 0x7e, 0xfe, 0x01, 0x20, 0x1b, 0x06, 0x86, 0x08, 0xb0, 0x47,
	0x79, 0x07, 0x07, 0x07, 0xb0, 0x32, 0xb3, 0x63, 0xfd, 0xcb, 0x00, 0x86, 0x0d, 0x79, 0xfe, 0xff,
	0x20, 0x04, 0xfd, 0x2c, 0x0e, 0x07, 0x2c, 0x7b, 0xd6, 0x08, 0x5f, 0xfe, 0x3e, 0x20, 0xc9, 0xdd,
	0x23, 0x15, 0x20, 0xc2, 0xe1, 0xd1, 0x01, 0x05, 0x00, 0x09, 0xeb, 0x09, 0xeb, 0xfd, 0xe1, 0xc1,
	0xc9, 0xe5, 0xdd, 0xe1, 0xd5, 0xfd, 0xe1, 0x06, 0x28, 0xc5, 0xdd, 0x4e, 0x00, 0xcd, 0x1c, 0x64,
	0xdd, 0x7e, 0x04, 0xfd, 0x71, 0x04, 0x4f, 0xcd, 0x1c, 0x64, 0xfd, 0x71, 0x00, 0xdd, 0x4e, 0x01,
	0xcd, 0x1c, 0x64, 0xdd, 0x7e, 0x03, 0xfd, 0x71, 0x03, 0x4f, 0xcd, 0x1c, 0x64, 0xfd, 0x71, 0x01,
	0xdd, 0x4e, 0x02, 0xcd, 0x1c, 0x64, 0xfd, 0x71, 0x02, 0x01, 0x05, 0x00, 0xdd, 0x09, 0xfd, 0x09,
	0xc1, 0x10, 0xc6, 0xc9, 0x06, 0x08, 0xcb, 0x19, 0x17, 0x10, 0xfb, 0x4f, 0xc9, 0xe5, 0x11, 0x00,
	0x9c, 0x06, 0x05, 0xc5, 0xe5, 0x06, 0x08, 0xc5, 0xe5, 0x06, 0x28, 0xc5, 0xcb, 0x16, 0xd5, 0x06,
	0x05, 0x1a, 0x1f, 0x12, 0x1c, 0x10, 0xfa, 0xd1, 0x01, 0x05, 0x00, 0x09, 0xc1, 0x10, 0xec, 0x1c,
	0x1c, 0x1c, 0x1c, 0x1c, 0xe1, 0xc1, 0x10, 0xdf, 0xe1, 0xc1, 0x23, 0x10, 0xd6, 0xd1, 0xd5, 0x21,
	0x00, 0x9c, 0x01, 0xc8, 0x00, 0xed, 0xb0, 0xe1, 0xc9, 0xdd, 0x21, 0x84, 0xac, 0x06, 0x3c, 0xdd,
	0x6e, 0x00, 0xdd, 0x66, 0x01, 0xdd, 0x7e, 0x04, 0x32, 0x75, 0x64, 0xaf, 0xcb, 0x46, 0x28, 0x02,
	0x3e, 0x01, 0xdd, 0x77, 0x05, 0x11, 0x06, 0x00, 0xdd, 0x19, 0x10, 0xe3, 0xc9, 0xdd, 0x21, 0x84,
	0xac, 0x06, 0x14, 0xc5, 0xdd, 0x6e, 0x00, 0xdd, 0x66, 0x01, 0xdd, 0x56, 0x02, 0xdd, 0x5e, 0x03,
	0xdd, 0x7e, 0x05, 0xfe, 0x01, 0x7a, 0x20, 0x01, 0x7b, 0x32, 0xa5, 0x64, 0xcb, 0x86, 0x24, 0x7c,
	0xe6, 0x07, 0x20, 0x18, 0x7c, 0xd6, 0x08, 0x67, 0x7d, 0xc6, 0x20, 0x6f, 0xe6, 0xe0, 0x20, 0x0c,
	0x7c, 0xc6, 0x08, 0x67, 0xe6, 0x18, 0xfe, 0x18, 0x20, 0x02, 0x26, 0x40, 0xdd, 0x75, 0x00, 0xdd,
	0x74, 0x01, 0x06, 0x01, 0xcd, 0x67, 0x64, 0x3a, 0xa5, 0x64, 0xcb, 0xf7, 0x32, 0xd8, 0x64, 0xcb,
	0xc6, 0xc1, 0x10, 0xaf, 0xc9, 0x0a, 0xc5, 0x4f, 0x06, 0x00, 0xdd, 0x21, 0xe0, 0x6a, 0xdd, 0x09,
	0xdd, 0x7e, 0x00, 0x82, 0x57, 0xcd, 0xf7, 0x64, 0xe1, 0x7e, 0x3c, 0xe6, 0x1f, 0x77, 0xc9, 0x06,
	0x05, 0xc5, 0x06, 0x08, 0xc5, 0x01, 0x05, 0x00, 0xeb, 0xed, 0xb0, 0xeb, 0x01, 0xfb, 0x00, 0x09,
	0xc1, 0x10, 0xf1, 0x01, 0x20, 0xf8, 0x09, 0xc1, 0x10, 0xe7, 0xc9, 0x11, 0x9b, 0x6e, 0xd5, 0xd5,
	0xd5, 0x21, 0x00, 0x40, 0xcd, 0xf7, 0x64, 0x21, 0x1b, 0x40, 0xd1, 0xcd, 0xf7, 0x64, 0x21, 0x60,
	0x50, 0xd1, 0xcd, 0xf7, 0x64, 0x21, 0x7b, 0x50, 0xd1, 0xcd, 0xf7, 0x64, 0x11, 0x00, 0xa9, 0x21,
	0x06, 0x40, 0xcd, 0xf7, 0x64, 0x11, 0xc8, 0xa9, 0x21, 0x0b, 0x40, 0xcd, 0xf7, 0x64, 0x11, 0x90,
	0xaa, 0x21, 0x10, 0x40, 0xcd, 0xf7, 0x64, 0x11, 0x58, 0xab, 0x21, 0x15, 0x40, 0xcd, 0xf7, 0x64,
	0x11, 0x06, 0x58, 0x21, 0x20, 0xac, 0x06, 0x05, 0xc5, 0x01, 0x14, 0x00, 0xed, 0xb0, 0x01, 0x0c,
	0x00, 0xeb, 0x09, 0xeb, 0xc1, 0x10, 0xf1, 0xcd, 0xc2, 0x6c, 0x21, 0x00, 0xa5, 0x22, 0x36, 0x5c,
	0x21, 0x00, 0x6b, 0xcd, 0x23, 0x67, 0x21, 0x00, 0x40, 0x11, 0x00, 0xc0, 0x01, 0x00, 0x1b, 0xed,
	0xb0, 0xcd, 0x44, 0x6e, 0x21, 0x00, 0xc0, 0x11, 0x00, 0x40, 0x01, 0x00, 0x1b, 0xed, 0xb0, 0xcd,
	0x33, 0x69, 0x3e, 0x01, 0x32, 0xbf, 0xb3, 0xdd, 0x21, 0x00, 0x9d, 0xcd, 0xca, 0x65, 0xcd, 0x4b,
	0x68, 0x7e, 0x32, 0xcb, 0xb3, 0xdd, 0x22, 0xc1, 0xb3, 0x21, 0x00, 0x00, 0x22, 0x78, 0x5c, 0xaf,
	0x32, 0xac, 0xde, 0x21, 0x00, 0x40, 0x11, 0x00, 0xc0, 0x01, 0x00, 0x1b, 0xed, 0xb0, 0xcd, 0x61,
	0x64, 0xc9, 0xdd, 0xe5, 0xe1, 0xaf, 0x32, 0x78, 0x5c, 0x16, 0x00, 0x7e, 0xcd, 0x50, 0x67, 0xa7,
	0x28, 0x22, 0xcd, 0x3a, 0x67, 0x7e, 0xa3, 0xfe, 0x42, 0x20, 0x01, 0x14, 0xfe, 0x43, 0xf5, 0x01,
	0x05, 0x00, 0x09, 0xf1, 0x20, 0x06, 0x7e, 0xfe, 0xc0, 0x20, 0x01, 0x14, 0x23, 0x23, 0x23, 0x7c,
	0xfe, 0xa5, 0x20, 0xd7, 0x7a, 0x32, 0xb5, 0xb3, 0x21, 0x00, 0x00, 0x22, 0xb8, 0xb3, 0x22, 0xba,
	0xb3, 0x22, 0xbc, 0xb3, 0xa7, 0x20, 0x12, 0x21, 0x44, 0x6b, 0xcd, 0x23, 0x67, 0x21, 0x0b, 0x09,
	0x22, 0xb6, 0xb3, 0x3e, 0x0e, 0x32, 0xbe, 0xb3, 0xc9, 0xfe, 0x0d, 0x30, 0x22, 0x32, 0xbb, 0xb3,
	0x21, 0x06, 0x0e, 0x22, 0xb6, 0xb3, 0x3e, 0x01, 0x32, 0xb8, 0xb3, 0x32, 0xc0, 0xb3, 0x3e, 0x08,
	0x32, 0xbe, 0xb3, 0xdd, 0xe5, 0xe1, 0x01, 0x06, 0x0a, 0x1e, 0x41, 0xcd, 0x91, 0x66, 0xc9, 0xfe,
	0x19, 0x30, 0x38, 0xa7, 0x1f, 0x32, 0xbc, 0xb3, 0xce, 0x00, 0x32, 0xbb, 0xb3, 0x21, 0x06, 0x06,
	0x22, 0xb6, 0xb3, 0x3e, 0x02, 0x32, 0xb8, 0xb3, 0x3d, 0x32, 0xc0, 0xb3, 0x3e, 0x08, 0x32, 0xbe,
	0xb3, 0xdd, 0xe5, 0xe1, 0x01, 0x06, 0x02, 0x1e, 0x41, 0x3a, 0xbb, 0xb3, 0x57, 0xcd, 0x91, 0x66,
	0x01, 0x06, 0x12, 0x3a, 0xbc, 0xb3, 0x57, 0xcd, 0x91, 0x66, 0xc9, 0x3e, 0x18, 0xcd, 0x4b, 0x66,
	0x22, 0xc3, 0xb3, 0x3e, 0x01, 0x32, 0xb9, 0xb3, 0xc9, 0xed, 0x43, 0xcf, 0xb3, 0xd5, 0x7e, 0xcd,
	0x50, 0x67, 0x1e, 0xff, 0xcd, 0x3a, 0x67, 0x16, 0x06, 0x7e, 0xa3, 0xfe, 0x42, 0x28, 0x14, 0xfe,
	0x43, 0xf5, 0x01, 0x05, 0x00, 0x09, 0xf1, 0x20, 0x05, 0x7e, 0xfe, 0xc0, 0x28, 0x0b, 0x23, 0x23,
	0x23, 0x18, 0xdb, 0x01, 0x05, 0x00, 0x09, 0x16, 0x04, 0x01, 0x0d, 0x00, 0xa7, 0xed, 0x42, 0x7a,
	0x32, 0xda, 0xb3, 0x11, 0xdb, 0xb3, 0x06, 0x08, 0x7e, 0xfe, 0x20, 0x30, 0x02, 0x3e, 0x2e, 0xfe,
	0x80, 0x38, 0x02, 0x3e, 0x2e, 0x12, 0x13, 0x23, 0x10, 0xee, 0x3e, 0xff, 0x12, 0xd1, 0xe5, 0x6b,
	0x26, 0x3e, 0x22, 0xd5, 0xb3, 0x21, 0x20, 0x20, 0x22, 0xd7, 0xb3, 0x3e, 0x10, 0x32, 0xd9, 0xb3,
	0x3e, 0x16, 0x32, 0xce, 0xb3, 0x21, 0x13, 0x01, 0x22, 0xd1, 0xb3, 0x21, 0x10, 0x05, 0x22, 0xd3,
	0xb3, 0xd5, 0x21, 0xce, 0xb3, 0xcd, 0x23, 0x67, 0xd1, 0xe1, 0x01, 0x08, 0x00, 0x09, 0x3a, 0xcf,
	0xb3, 0x3c, 0x32, 0xcf, 0xb3, 0x1c, 0x15, 0xc2, 0x95, 0x66, 0xc9, 0xe5, 0x2a, 0xca, 0xaf, 0xd9,
	0xfd, 0x2a, 0xc8, 0xaf, 0x3e, 0x02, 0xcd, 0x01, 0x16, 0xe1, 0x7e, 0xfe, 0xff, 0xc8, 0xd7, 0x23,
	0x18, 0xf8, 0xd5, 0x0e, 0x00, 0x06, 0x09, 0x11, 0x6e, 0x6b, 0x1a, 0xbe, 0x28, 0x02, 0x0e, 0xff,
	0x23, 0x13, 0x10, 0xf6, 0xd1, 0x59, 0x2b, 0xc9, 0xfe, 0x01, 0xc0, 0x01, 0x10, 0x00, 0x09, 0x7e,
	0x18, 0xf6, 0xfd, 0xe5, 0xdd, 0xe5, 0xe5, 0xd5, 0xc5, 0xf5, 0xd9, 0xe5, 0xd5, 0xc5, 0x2a, 0xca,
	0xaf, 0xd9, 0x08, 0xf5, 0xfd, 0x2a, 0xc8, 0xaf, 0xcd, 0x56, 0xeb, 0x2a, 0x78, 0x5c, 0x23, 0x22,
	0x78, 0x5c, 0x3a, 0xac, 0xde, 0xc6, 0x02, 0x32, 0xac, 0xde, 0xcd, 0xa8, 0x6b, 0xcd, 0x07, 0x6d,
	0x3a, 0x78, 0x5c, 0xe6, 0x03, 0xfe, 0x03, 0x20, 0x21, 0xcd, 0x4b, 0x68, 0xed, 0x5b, 0xbe, 0xb3,
	0x43, 0x72, 0x23, 0x10, 0xfc, 0xcb, 0x72, 0xcb, 0xf2, 0x28, 0x0b, 0xcb, 0xb2, 0x14, 0xcb, 0x5a,
	0x28, 0x04, 0x14, 0x14, 0xcb, 0x9a, 0x7a, 0x32, 0xbf, 0xb3, 0x3a, 0x78, 0x5c, 0xfe, 0x32, 0x20,
	0x58, 0x2a, 0xb6, 0xb3, 0x22, 0xcc, 0xb3, 0x3a, 0xbe, 0xb3, 0x32, 0xec, 0xb3, 0x21, 0xcc, 0xb3,
	0x22, 0x4d, 0x68, 0xcd, 0x4b, 0x68, 0x2a, 0xc9, 0xb3, 0x7c, 0x07, 0x07, 0x07, 0xf6, 0xc0, 0x67,
	0x22, 0xae, 0xde, 0x3a, 0xec, 0xb3, 0x47, 0xc5, 0xe5, 0x11, 0xed, 0xb3, 0xd5, 0x06, 0x08, 0x7e,
	0x12, 0x24, 0x13, 0x10, 0xfa, 0xe1, 0xd1, 0xd5, 0x06, 0x08, 0x0e, 0x08, 0xe5, 0xcb, 0x16, 0x1f,
	0x23, 0x0d, 0x20, 0xf9, 0x12, 0x14, 0xe1, 0x10, 0xf1, 0xe1, 0x23, 0xc1, 0x10, 0xd9, 0x21, 0xb6,
	0xb3, 0x22, 0x4d, 0x68, 0xcd, 0xa5, 0x6c, 0x18, 0x1f, 0xfe, 0x3c, 0x28, 0xb0, 0xfe, 0x46, 0x28,
	0xac, 0xfe, 0x50, 0x28, 0xa8, 0xfe, 0x5a, 0x20, 0x0f, 0x3e, 0xc9, 0x32, 0xdb, 0x67, 0xcd, 0xc5,
	0x67, 0x3e, 0x3a, 0x32, 0xdb, 0x67, 0x18, 0xd6, 0x3a, 0x78, 0x5c, 0xe6, 0x07, 0xfe, 0x07, 0xcc,
	0x67, 0x68, 0xd9, 0xf1, 0x08, 0xc1, 0xd1, 0xe1, 0xd9, 0xf1, 0xc1, 0xd1, 0xe1, 0xdd, 0xe1, 0xfd,
	0xe1, 0xfb, 0xc9, 0xed, 0x5b, 0xb6, 0xb3, 0x21, 0x00, 0x00, 0x01, 0x20, 0x00, 0x7b, 0xa7, 0x28,
	0x04, 0x09, 0x1d, 0x18, 0xf8, 0x4a, 0x09, 0x22, 0xc9, 0xb3, 0x01, 0x00, 0x58, 0x09, 0xc9, 0x0e,
	0x41, 0x21, 0x56, 0x6b, 0x7e, 0x0f, 0x0f, 0xe6, 0x38, 0xf6, 0x87, 0x32, 0x79, 0x68, 0x3e, 0xff,
	0xcb, 0x87, 0xdb, 0xfe, 0x2f, 0x47, 0x7e, 0xe6, 0x1f, 0xa0, 0xc4, 0x54, 0x6a, 0x0c, 0x23, 0x79,
	0xfe, 0x59, 0x20, 0xe0, 0x3e, 0xf7, 0xdb, 0xfe, 0x1f, 0xd4, 0x6a, 0x69, 0x1f, 0xd4, 0x6a, 0x69,
	0x1f, 0xd4, 0xc3, 0x69, 0x1f, 0xd4, 0x3d, 0x6a, 0x1f, 0xd4, 0x42, 0x6a, 0x3e, 0xef, 0xdb, 0xfe,
	0x1f, 0xd4, 0x42, 0x6a, 0x1f, 0xd4, 0x3d, 0x6a, 0x1f, 0xd4, 0xc3, 0x69, 0x1f, 0xd4, 0x6a, 0x69,
	0x1f, 0xd4, 0x6a, 0x69, 0x3e, 0x00, 0x1f, 0xdc, 0x6a, 0x69, 0x1f, 0xdc, 0x6a, 0x69, 0x1f, 0xdc,
	0xc3, 0x69, 0x1f, 0xdc, 0x3d, 0x6a, 0x1f, 0xdc, 0x42, 0x6a, 0x3e, 0xfe, 0xdb, 0xfe, 0x1f, 0x38,
	0x0f, 0x2a, 0xc1, 0xb3, 0x01, 0x01, 0x9d, 0xa7, 0xed, 0x42, 0x38, 0x04, 0xcd, 0x89, 0x65, 0xc9,
	0x3e, 0xbf, 0xdb, 0xfe, 0x1f, 0xd4, 0x42, 0x6a, 0x3e, 0x7f, 0xdb, 0xfe, 0x1f, 0x38, 0x21, 0x2a,
	0xca, 0xaf, 0xd9, 0xfd, 0x2a, 0xc8, 0xaf, 0xcd, 0x44, 0x6e, 0x21, 0x00, 0x9d, 0x11, 0x00, 0x00,
	0x01, 0x05, 0x08, 0xf3, 0xed, 0x56, 0xcd, 0x13, 0x3d, 0xf3, 0xed, 0x5e, 0xcd, 0x89, 0x65, 0xc9,
	0x1f, 0xd8, 0x3a, 0xb9, 0xb3, 0xa7, 0xc8, 0x2a, 0xc3, 0xb3, 0xaf, 0x32, 0xb9, 0xb3, 0x22, 0xa1,
	0x65, 0xcd, 0x89, 0x65, 0x21, 0x00, 0x9d, 0x22, 0xa1, 0x65, 0xc9, 0x21, 0xc0, 0x40, 0x0e, 0x60,
	0x06, 0x20, 0x36, 0x00, 0x2c, 0x10, 0xfb, 0x0d, 0x28, 0x1a, 0x7d, 0xd6, 0x20, 0x6f, 0x24, 0x7c,
	0xe6, 0x07, 0x20, 0xec, 0x7c, 0xd6, 0x08, 0x67, 0x7d, 0xc6, 0x20, 0x6f, 0x20, 0xe2, 0x7c, 0xc6,
	0x08, 0x67, 0x18, 0xdc, 0x21, 0xc0, 0x58, 0x11, 0xc1, 0x58, 0x01, 0x7f, 0x01, 0x36, 0x07, 0xed,
	0xb0, 0xc9, 0xf5, 0x3a, 0xbc, 0xb3, 0xa7, 0x20, 0x02, 0xf1, 0xc9, 0xcd, 0x4b, 0x68, 0x3a, 0xbe,
	0xb3, 0x47, 0x3a, 0xcb, 0xb3, 0x77, 0x23, 0x10, 0xfc, 0x3a, 0xbb, 0xb3, 0x47, 0x3a, 0xc0, 0xb3,
	0x4f, 0x3d, 0x90, 0x30, 0x23, 0xfe, 0xff, 0x20, 0x13, 0x2a, 0xbb, 0xb3, 0x7c, 0xbd, 0x28, 0x0c,
	0x3e, 0x01, 0x32, 0xc0, 0xb3, 0x3e, 0x06, 0x32, 0xb6, 0xb3, 0x18, 0x16, 0x79, 0x80, 0x32, 0xc0,
	0xb3, 0x3e, 0x16, 0x32, 0xb7, 0xb3, 0x18, 0x0a, 0x79, 0x90, 0x32, 0xc0, 0xb3, 0x3e, 0x06, 0x32,
	0xb7, 0xb3, 0xcd, 0x4b, 0x68, 0x7e, 0x32, 0xcb, 0xb3, 0xf1, 0xc9, 0xf5, 0x06, 0x00, 0x3a, 0xbc,
	0xb3, 0xa7, 0x20, 0x09, 0x3a, 0xbb, 0xb3, 0xa7, 0x28, 0x9f, 0x3d, 0x28, 0x9c, 0xc5, 0xcd, 0x4b,
	0x68, 0x3a, 0xbe, 0xb3, 0x47, 0x3a, 0xcb, 0xb3, 0x77, 0x23, 0x10, 0xfc, 0xc1, 0x3a, 0xc0, 0xb3,
	0x4f, 0xed, 0x5b, 0xbb, 0xb3, 0x3a, 0xb6, 0xb3, 0x6f, 0x3a, 0xb7, 0xb3, 0xfe, 0x16, 0x28, 0x21,
	0x78, 0xa7, 0x20, 0x0e, 0x79, 0xbb, 0x3e, 0x06, 0x26, 0x01, 0x28, 0x2f, 0x61, 0x24, 0x7d, 0x3c,
	0x18, 0x29, 0x79, 0xfe, 0x01, 0x20, 0x04, 0x63, 0x7b, 0x18, 0x1e, 0x61, 0x25, 0x7d, 0x3d, 0x18,
	0x1a, 0x78, 0xa7, 0x20, 0x0b, 0x7b, 0x82, 0xb9, 0x20, 0xe2, 0x63, 0x24, 0x3e, 0x06, 0x18, 0x0b,
	0x7b, 0x3c, 0xb9, 0x20, 0xe6, 0x7b, 0x82, 0x67, 0x7a, 0xc6, 0x05, 0x32, 0xb6, 0xb3, 0x7c, 0x32,
	0xc0, 0xb3, 0xc3, 0xba, 0x69, 0x06, 0x01, 0xf5, 0x18, 0x84, 0xf5, 0x3a, 0xbb, 0xb3, 0x47, 0x3a,
	0xbc, 0xb3, 0xb0, 0xca, 0x71, 0x69, 0x3a, 0xc0, 0xb3, 0xc6, 0x40, 0x4f, 0x3a, 0xb5, 0xb3, 0xc6,
	0x40, 0xb9, 0xd8, 0x06, 0x40, 0xd9, 0x2a, 0xc1, 0xb3, 0x7e, 0xcd, 0x50, 0x67, 0x1e, 0xff, 0xcd,
	0x3a, 0x67, 0x16, 0xec, 0x7e, 0xa3, 0xfe, 0x42, 0x28, 0x14, 0xfe, 0x43, 0xf5, 0x01, 0x05, 0x00,
	0x09, 0xf1, 0x20, 0x05, 0x7e, 0xfe, 0xc0, 0x28, 0x0b, 0x23, 0x23, 0x23, 0x18, 0xdb, 0x01, 0x05,
	0x00, 0x09, 0x16, 0xf7, 0x01, 0x0d, 0x00, 0xa7, 0xed, 0x42, 0xd9, 0x04, 0x78, 0xb9, 0xd9, 0x7e,
	0x36, 0x01, 0x20, 0xc5, 0x77, 0xd5, 0xe5, 0x21, 0x4c, 0x5d, 0x72, 0x23, 0x23, 0xeb, 0xe1, 0x01,
	0x08, 0x00, 0xed, 0xb0, 0x13, 0x0e, 0x20, 0xe1, 0x7c, 0xfe, 0xf7, 0x28, 0x02, 0x0e, 0xaf, 0x79,
	0x12, 0x21, 0x00, 0x00, 0x22, 0x78, 0x5c, 0x3a, 0xce, 0xaf, 0xed, 0x47, 0x2a, 0xca, 0xaf, 0xd9,
	0xfd, 0x2a, 0xc8, 0xaf, 0xed, 0x7b, 0xcc, 0xaf, 0x21, 0x00, 0x3c, 0x22, 0x36, 0x5c, 0xcd, 0x4b,
	0x6e, 0xcd, 0x75, 0x6e, 0xed, 0x56, 0xfb, 0xc9, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	0x08, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
	0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x16, 0x13, 0x07, 0x13, 0x01, 0x10, 0x05, 0x53,
	0x50, 0x41, 0x43, 0x45, 0x20, 0x20, 0x54, 0x4f, 0x20, 0x4e, 0x45, 0x57, 0x20, 0x44, 0x49, 0x53,
	0x4b, 0x16, 0x14, 0x07, 0x22, 0x53, 0x53, 0x22, 0x20, 0x54, 0x4f, 0x20, 0x4e, 0x45, 0x58, 0x54,
	0x20, 0x50, 0x41, 0x47, 0x45, 0x53, 0x16, 0x15, 0x07, 0x22, 0x43, 0x53, 0x22, 0x20, 0x54, 0x4f,
	0x20, 0x46, 0x49, 0x52, 0x53, 0x54, 0x20, 0x50, 0x41, 0x47, 0x45, 0xff, 0x16, 0x0b, 0x09, 0x4e,
	0x4f, 0x20, 0x45, 0x58, 0x45, 0x20, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x20, 0x21, 0xff, 0x21, 0xf0,
	0x08, 0x24, 0x44, 0x28, 0x30, 0xd0, 0xa4, 0xc8, 0xc4, 0xc2, 0xe4, 0xe8, 0xa2, 0xa1, 0x41, 0x48,
	0x22, 0x50, 0xa8, 0x10, 0x42, 0x04, 0x62, 0x6f, 0x6f, 0x74, 0x20, 0x20, 0x20, 0x20, 0x42, 0x08,
	0x10, 0x13, 0x17, 0x1f, 0x05, 0x0c, 0x15, 0x1b, 0x22, 0x01, 0x03, 0x0a, 0x1d, 0x24, 0x27, 0x07,
	0x0e, 0x19, 0x20, 0x02, 0x0b, 0x12, 0x16, 0x1c, 0x26, 0x00, 0x0f, 0x1e, 0x23, 0x09, 0x04, 0x11,
	0x18, 0x25, 0x14, 0x06, 0x0d, 0x1a, 0x21, 0x13, 0x12, 0x0f, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x00,
	0x3a, 0xac, 0xde, 0xa7, 0x20, 0x20, 0x2a, 0xa8, 0xde, 0x23, 0x7c, 0xe6, 0x07, 0x67, 0x22, 0xa8,
	0xde, 0x06, 0x08, 0x4e, 0x21, 0xec, 0xad, 0xed, 0x5f, 0xae, 0xa9, 0x81, 0x4f, 0x3a, 0xb0, 0xb3,
	0xa9, 0x77, 0x23, 0x10, 0xf2, 0xc9, 0x3a, 0xac, 0xde, 0xe6, 0x3f, 0xfe, 0x3e, 0x20, 0x21, 0x3a,
	0xb0, 0xde, 0x3c, 0xe6, 0x07, 0x32, 0xb0, 0xde, 0x28, 0x08, 0x3a, 0xac, 0xde, 0xd6, 0x02, 0x32,
	0xac, 0xde, 0x3e, 0xc9, 0x32, 0x1c, 0x6c, 0xcd, 0x00, 0x6c, 0x3e, 0x3a, 0x32, 0x1c, 0x6c, 0xc9,
	0x3a, 0xac, 0xde, 0xe6, 0x07, 0xfe, 0x02, 0xc0, 0x3a, 0xac, 0xde, 0x07, 0x07, 0x07, 0xe6, 0x06,
	0x4f, 0x06, 0x00, 0x21, 0xec, 0xad, 0x09, 0xcd, 0x59, 0x6c, 0xf5, 0xd4, 0xae, 0x6b, 0xf1, 0x30,
	0xe7, 0xcd, 0x74, 0x6c, 0x3a, 0xac, 0xde, 0xe6, 0x20, 0x0e, 0x60, 0x20, 0x02, 0x0e, 0x00, 0x3a,
	0xac, 0xde, 0x07, 0x07, 0xa9, 0xe6, 0x60, 0x4f, 0x06, 0x00, 0x21, 0x63, 0x6f, 0x09, 0xeb, 0x06,
	0x10, 0x2a, 0xaa, 0xde, 0x4e, 0x1a, 0xb1, 0x77, 0x2c, 0x13, 0x4e, 0x1a, 0xb1, 0x77, 0x13, 0x2d,
	0x24, 0x7c, 0xe6, 0x07, 0x20, 0x08, 0x7c, 0xd6, 0x08, 0x67, 0x7d, 0xc6, 0x20, 0x6f, 0x10, 0xe4,
	0xc9, 0x06, 0x1a, 0x23, 0x7e, 0xe6, 0x18, 0x28, 0x06, 0xfe, 0x10, 0x28, 0x02, 0x06, 0x1f, 0x2b,
	0x7e, 0xfe, 0xe0, 0xd0, 0xe6, 0x1f, 0xb8, 0xd0, 0xee, 0x1f, 0xb8, 0xc9, 0x23, 0x7e, 0xe6, 0x18,
	0xfe, 0x18, 0x20, 0x02, 0x3e, 0x08, 0x2b, 0x6e, 0xf6, 0x40, 0x67, 0x22, 0xaa, 0xde, 0x06, 0x10,
	0x7c, 0xf6, 0x80, 0x57, 0x5d, 0x1a, 0x77, 0x2c, 0x1c, 0x1a, 0x77, 0x2d, 0x24, 0x7c, 0xe6, 0x07,
	0x20, 0x08, 0x7c, 0xd6, 0x08, 0x67, 0x7d, 0xc6, 0x20, 0x6f, 0x10, 0xe4, 0xc9, 0x2a, 0xae, 0xde,
	0x7c, 0xe6, 0x7f, 0x57, 0x5d, 0x06, 0x08, 0xc5, 0x3a, 0xec, 0xb3, 0x4f, 0x06, 0x00, 0xe5, 0xd5,
	0xed, 0xb0, 0xd1, 0xe1, 0x24, 0x14, 0xc1, 0x10, 0xee, 0xc9, 0x21, 0x00, 0x58, 0xcd, 0xdb, 0x6c,
	0x21, 0x7b, 0x5a, 0xcd, 0xdb, 0x6c, 0x11, 0x1b, 0x58, 0xcd, 0xf2, 0x6c, 0x11, 0x60, 0x5a, 0xcd,
	0xf2, 0x6c, 0xc9, 0x06, 0x05, 0x11, 0xf4, 0xad, 0x0e, 0x05, 0x1a, 0x77, 0x23, 0x0d, 0x20, 0xfb,
	0x13, 0xc5, 0x01, 0x1b, 0x00, 0x09, 0xc1, 0x10, 0xef, 0xc9, 0x06, 0x05, 0xc5, 0x01, 0x05, 0x00,
	0x21, 0xf4, 0xad, 0xed, 0xb0, 0xeb, 0x01, 0x1b, 0x00, 0x09, 0xeb, 0xc1, 0x10, 0xee, 0xc9, 0x3a,
	0x78, 0x5c, 0xfe, 0x40, 0xd0, 0x21, 0x06, 0x58, 0x22, 0x41, 0x6d, 0x21, 0x19, 0x58, 0x22, 0x44,
	0x6d, 0x21, 0x80, 0x58, 0x22, 0x57, 0x6d, 0x3a, 0x79, 0x5c, 0xe6, 0x01, 0x28, 0x12, 0x21, 0x66,
	0x5a, 0x22, 0x41, 0x6d, 0x21, 0x79, 0x5a, 0x22, 0x44, 0x6d, 0x21, 0xe0, 0x5a, 0x22, 0x57, 0x6d,
	0x3a, 0x78, 0x5c, 0xa7, 0x20, 0x09, 0x3e, 0x02, 0x32, 0x06, 0x58, 0x32, 0x19, 0x58, 0xc9, 0xe6,
	0x01, 0xc0, 0x3a, 0x78, 0x5c, 0x0f, 0xe6, 0x1f, 0xfe, 0x1b, 0xd0, 0x4f, 0x06, 0x05, 0x21, 0x80,
	0x58, 0x0d, 0xcd, 0x6d, 0x6d, 0x0c, 0xcd, 0x8d, 0x6d, 0x0c, 0xc5, 0x01, 0x20, 0x00, 0xa7, 0xed,
	0x42, 0xc1, 0x10, 0xed, 0xc9, 0xc5, 0xe5, 0x7d, 0xb1, 0x6f, 0x5d, 0x7c, 0xf6, 0x80, 0x57, 0xe5,
	0xd5, 0xeb, 0x01, 0x03, 0x00, 0xed, 0xb0, 0xe1, 0xd1, 0x7d, 0xee, 0x1f, 0x6f, 0x5d, 0x0e, 0x03,
	0xed, 0xb8, 0xe1, 0xc1, 0xc9, 0xc5, 0xe5, 0x7d, 0xb1, 0x6f, 0xe5, 0xcd, 0xb1, 0x6d, 0x23, 0xcd,
	0xbd, 0x6d, 0x23, 0xcd, 0xb1, 0x6d, 0xe1, 0x7d, 0xee, 0x1f, 0x6f, 0xcd, 0xb1, 0x6d, 0x2b, 0xcd,
	0xbd, 0x6d, 0x2b, 0xcd, 0xb1, 0x6d, 0xe1, 0xc1, 0xc9, 0x7d, 0xe6, 0x1f, 0xfe, 0x06, 0xd8, 0xfe,
	0x1a, 0xd0, 0x36, 0x02, 0xc9, 0x7d, 0xe6, 0x1f, 0xfe, 0x06, 0xd8, 0xfe, 0x1a, 0xd0, 0x36, 0x42,
	0xc9, 0x21, 0x00, 0xa9, 0xcd, 0x38, 0x6e, 0x21, 0xc8, 0xa9, 0xcd, 0x38, 0x6e, 0x21, 0x90, 0xaa,
	0xcd, 0x38, 0x6e, 0x21, 0x58, 0xab, 0xcd, 0x38, 0x6e, 0xf3, 0x11, 0x00, 0xa9, 0x21, 0x66, 0xd0,
	0xcd, 0xf7, 0x64, 0x11, 0xc8, 0xa9, 0x21, 0x6b, 0xd0, 0xcd, 0xf7, 0x64, 0x11, 0x90, 0xaa, 0x21,
	0x70, 0xd0, 0xcd, 0xf7, 0x64, 0x11, 0x58, 0xab, 0x21, 0x75, 0xd0, 0xcd, 0xf7, 0x64, 0x06, 0x05,
	0x21, 0x06, 0xd8, 0x11, 0xe6, 0xda, 0xc5, 0x01, 0x14, 0x00, 0xed, 0xb0, 0x0e, 0x0c, 0x09, 0x0e,
	0x34, 0xa7, 0xeb, 0xed, 0x42, 0xeb, 0xc1, 0x10, 0xed, 0x21, 0x00, 0xd0, 0x11, 0x00, 0x50, 0x01,
	0x00, 0x08, 0xed, 0xb0, 0x21, 0x60, 0xda, 0x11, 0x60, 0x5a, 0x0e, 0xa0, 0xed, 0xb0, 0xfb, 0xc9,
	0xcd, 0x25, 0x64, 0xcd, 0x25, 0x64, 0x54, 0x5d, 0xcd, 0xd9, 0x63, 0xc9, 0x21, 0x30, 0x75, 0xcd,
	0x52, 0x6e, 0xc9, 0x21, 0x67, 0x6e, 0xcd, 0x52, 0x6e, 0xc9, 0xaf, 0x01, 0xfd, 0xff, 0xed, 0x79,
	0xf5, 0x7e, 0x01, 0xfd, 0xbf, 0xed, 0x79, 0x23, 0xf1, 0x3c, 0xfe, 0x0e, 0xc8, 0x18, 0xec, 0x30,
	0x00, 0x01, 0x00, 0x50, 0x00, 0x00, 0x38, 0x10, 0x10, 0x10, 0xc4, 0x50, 0x01, 0x16, 0x08, 0x0e,
	0x10, 0x21, 0x00, 0x40, 0x41, 0xaf, 0xcb, 0x1e, 0x23, 0xaf, 0xcb, 0x16, 0x23, 0x10, 0xf6, 0x41,
	0xaf, 0xcb, 0x16, 0x23, 0xaf, 0xcb, 0x1e, 0x23, 0x10, 0xf6, 0x7c, 0xfe, 0x58, 0x20, 0xe5, 0x15,
	0x20, 0xdd, 0xc9, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x72,
	0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x80, 0x00, 0x00, 0x03, 0xd0, 0x40,
	0x00, 0x00, 0x07, 0xa8, 0x20, 0x00, 0x00, 0x0b, 0x54, 0x10, 0x00, 0x00, 0x1e, 0xaa, 0x08, 0x00,
	0x00, 0x2d, 0x55, 0x04, 0x00, 0x00, 0x7a, 0xaa, 0x82, 0x00, 0x00, 0xb5, 0x55, 0x41, 0x00, 0x01,
	0x6a, 0xaa, 0xa0, 0x80, 0x02, 0xd5, 0x45, 0x50, 0x40, 0x05, 0x2a, 0x82, 0xa8, 0x20, 0x09, 0x55,
	0x01, 0x54, 0x10, 0x12, 0xaa, 0x00, 0xaa, 0x08, 0x25, 0x54, 0x00, 0x55, 0x04, 0x22, 0xa8, 0x00,
	0x2a, 0x84, 0x25, 0x50, 0x00, 0x15, 0x44, 0x2a, 0xa4, 0x00, 0x3a, 0xa4, 0x35, 0x42, 0x00, 0x7d,
	0x54, 0x2a, 0xa1, 0x00, 0xba, 0xa8, 0x15, 0x51, 0x01, 0xf5, 0x50, 0x0a, 0xa9, 0x03, 0xea, 0xa0,
	0x05, 0x55, 0x05, 0xd5, 0x40, 0x02, 0xab, 0x0f, 0xaa, 0x80, 0x01, 0x55, 0x17, 0x55, 0x00, 0x00,
	0xaa, 0x2e, 0xaa, 0x00, 0x00, 0x54, 0x55, 0x54, 0x00, 0x00, 0x28, 0x9a, 0xa8, 0x00, 0x00, 0x11,
	0x35, 0x50, 0x00, 0x00, 0x01, 0x2a, 0xa0, 0x00, 0x00, 0x01, 0x55, 0x40, 0x00, 0x00, 0x01, 0xaa,
	0x80, 0x00, 0x00, 0x01, 0x55, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00,
	0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x00, 0x80, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x05, 0xd0, 0x00, 0x80, 0x00,
	0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x90, 0x02, 0x80, 0x01, 0xc0, 0x2f, 0xf4, 0x01, 0xc0, 0x00,
	0xa0, 0x04, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
	0x80, 0x10, 0x08, 0x00, 0x80, 0x04, 0x80, 0x02, 0xa0, 0x01, 0xc0, 0x5f, 0xfd, 0x01, 0xc0, 0x02,
	0x80, 0x04, 0x90, 0x00, 0x88, 0x10, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x10, 0x10, 0x00, 0x10, 0x00,
	0x00, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7e, 0x24, 0x24, 0x7e, 0x24, 0x00,
	0x00, 0x08, 0x3e, 0x68, 0x3e, 0x0a, 0x7e, 0x08, 0x00, 0x66, 0x4c, 0x18, 0x30, 0x66, 0x4e, 0x00,
	0x18, 0x24, 0x2c, 0x78, 0xda, 0xcc, 0x7e, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x30, 0x18, 0x18, 0x18, 0x18, 0x30, 0x00,
	0x00, 0x00, 0x14, 0x08, 0x7e, 0x18, 0x2c, 0x00, 0x00, 0x00, 0x08, 0x08, 0x7e, 0x18, 0x18, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00,
	0x38, 0x6c, 0xce, 0xd6, 0xe6, 0x6c, 0x38, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x3e, 0x7c, 0x00,
	0x78, 0xcc, 0x1c, 0x38, 0x70, 0xe6, 0xfe, 0x00, 0x7e, 0xcc, 0x18, 0x3c, 0x0e, 0xce, 0x7c, 0x00,
	0x24, 0x6c, 0xcc, 0xcc, 0xfc, 0x0c, 0x0c, 0x00, 0xfe, 0xc2, 0xf8, 0xcc, 0x0e, 0xce, 0x7c, 0x00,
	0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0x7e, 0x66, 0x0e, 0x1c, 0x38, 0x30, 0x30, 0x00,
	0x7c, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00,
	0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30,
	0x00, 0x00, 0x0c, 0x18, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x7e, 0x00, 0x00,
	0x00, 0x00, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x1c, 0x30, 0x00, 0x30, 0x00,
	0x00, 0x3c, 0x4a, 0x56, 0xfe, 0xc0, 0x7c, 0x00, 0x3c, 0x66, 0xc6, 0xfe, 0xc6, 0xe6, 0x66, 0x00,
	0xf8, 0xcc, 0xcc, 0xfc, 0xc6, 0xc6, 0xfc, 0x00, 0x38, 0x6c, 0xc6, 0xc0, 0xc0, 0xe6, 0x7c, 0x00,
	0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00, 0xfe, 0xe6, 0x60, 0x7c, 0x60, 0xe6, 0xfe, 0x00,
	0xfe, 0xe6, 0x60, 0x7c, 0x60, 0xe0, 0xc0, 0x00, 0x3c, 0x66, 0xc0, 0xde, 0xc6, 0xee, 0x7c, 0x00,
	0xc4, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x46, 0x00, 0x7e, 0x98, 0x30, 0x30, 0x30, 0x1a, 0xfc, 0x00,
	0x3e, 0x0c, 0x0c, 0xe6, 0x66, 0xc6, 0x7c, 0x00, 0xe6, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0xc6, 0x00,
	0xc0, 0xe0, 0x60, 0x60, 0x60, 0xe6, 0xfe, 0x00, 0x46, 0xee, 0xfe, 0xd6, 0xd6, 0xc6, 0x46, 0x00,
	0xc4, 0xe6, 0xf6, 0xde, 0xce, 0xce, 0x46, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xee, 0x7c, 0x00,
	0xfc, 0xe6, 0xc6, 0xce, 0xfc, 0xc0, 0xc0, 0x00, 0x38, 0x6c, 0xc6, 0xd6, 0xce, 0xec, 0x7a, 0x00,
	0xfc, 0xc6, 0xc6, 0xfc, 0xd8, 0xcc, 0xc6, 0x00, 0x3e, 0x66, 0x70, 0x1c, 0xc6, 0xc6, 0x7c, 0x00,
	0xfe, 0xba, 0x18, 0x18, 0x18, 0x38, 0x30, 0x00, 0xe6, 0x66, 0xc6, 0xc6, 0xc6, 0xe6, 0x7c, 0x00,
	0xce, 0xcc, 0xc6, 0xc6, 0x66, 0x7c, 0x38, 0x00, 0xce, 0xc6, 0xd6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
	0xc6, 0xee, 0x6c, 0x38, 0x6c, 0xee, 0xc6, 0x00, 0xc6, 0xc6, 0x6e, 0x3c, 0x18, 0x18, 0x18, 0x00,
	0x76, 0xec, 0x98, 0x30, 0x62, 0xde, 0xbc, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x30, 0x30, 0x3c, 0x00,
	0x00, 0x40, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x1c, 0x04, 0x04, 0x0c, 0x0c, 0x3c, 0x00,
	0x00, 0x08, 0x1c, 0x2a, 0x08, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
	0x00, 0x1c, 0x22, 0x78, 0x60, 0x60, 0xfc, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x3e, 0x66, 0x3e, 0x00,
	0x00, 0x20, 0x20, 0x3c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x60, 0x60, 0x3c, 0x00,
	0x00, 0x02, 0x02, 0x1e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x7c, 0x60, 0x3e, 0x00,
	0x00, 0x0c, 0x10, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x66, 0x3e, 0x06, 0x3c,
	0x00, 0x20, 0x20, 0x3c, 0x66, 0x66, 0x66, 0x00, 0x00, 0x08, 0x00, 0x08, 0x18, 0x18, 0x3c, 0x00,
	0x00, 0x04, 0x00, 0x04, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x20, 0x28, 0x30, 0x70, 0x78, 0x6c, 0x00,
	0x00, 0x10, 0x10, 0x10, 0x30, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x34, 0x2a, 0x6a, 0x6a, 0x6a, 0x00,
	0x00, 0x00, 0x3c, 0x22, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x66, 0x66, 0x3c, 0x00,
	0x00, 0x00, 0x3c, 0x22, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x3c, 0x44, 0xcc, 0x7c, 0x0c, 0x0e,
	0x00, 0x00, 0x1c, 0x20, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x3c, 0x06, 0x7c, 0x00,
	0x00, 0x10, 0x38, 0x10, 0x30, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x22, 0x22, 0x66, 0x66, 0x3c, 0x00,
	0x00, 0x00, 0x44, 0x44, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x6a, 0x7e, 0x3c, 0x00,
	0x00, 0x00, 0x22, 0x14, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x22, 0x22, 0x66, 0x3e, 0x06, 0x3c,
	0x00, 0x00, 0x3e, 0x04, 0x18, 0x30, 0x7e, 0x00, 0x00, 0x0e, 0x08, 0x30, 0x10, 0x18, 0x1e, 0x00,
	0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x38, 0x08, 0x04, 0x08, 0x18, 0x78, 0x00,
	0x00, 0x12, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x99, 0xa1, 0xa1, 0x99, 0x42, 0x3c,
	0x09, 0x20, 0x00, 0x00, 0x00, 0x05, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x91, 0xc0, 0x00, 0x07, 0xbe,
	0xe4, 0x1e, 0x00, 0x70, 0x02, 0x7e, 0xa0, 0xff, 0x02, 0x01, 0x21, 0xf5, 0x00, 0x57, 0x09, 0x60,
	0x1f, 0x95, 0xf8, 0x01, 0x20, 0x00, 0xff, 0xe0, 0x01, 0x11, 0xfc, 0x2d, 0xff, 0x01, 0x13, 0x9f,
	0xff, 0xe1, 0x00, 0x17, 0xff, 0xff, 0x99, 0x01, 0x16, 0x04, 0xbf, 0xfe, 0x00, 0x2c, 0x01, 0xfd,
	0xdf, 0x01, 0x2c, 0xff, 0x07, 0x57, 0x00, 0x3f, 0x00, 0x0e, 0xbb, 0x00, 0x78, 0x00, 0x0a, 0x96,
	0x00, 0x00, 0x00, 0x15, 0x02, 0x00, 0x10, 0x00, 0x20, 0x0c, 0x00, 0x00, 0x00, 0x51, 0x04, 0x00,
	0x10, 0x00, 0x80, 0x09, 0x00, 0x10, 0x83, 0x00, 0x12, 0x01, 0x10, 0x0a, 0x00, 0xa4, 0x00, 0x12,
	0x3c, 0x21, 0x48, 0x00, 0x54, 0xd2, 0x12, 0xb0, 0x00, 0x3b, 0x29, 0x41, 0x50, 0x57, 0xec, 0xd1,
	0x22, 0xa0, 0x00, 0x5b, 0xe4, 0x0c, 0x40, 0x00, 0xbf, 0x5b, 0x58, 0x80, 0x00, 0x77, 0xff, 0xf1,
	0x03, 0x02, 0xdf, 0xb7, 0x56, 0xfc, 0x01, 0xbf, 0xff, 0xe8, 0x00, 0x01, 0x3f, 0x7f, 0xc7, 0x29,
	0x02, 0x63, 0xc7, 0xf1, 0xff, 0x02, 0xdf, 0x8b, 0xf8, 0x1b, 0x04, 0x07, 0xfe, 0xdf, 0xff, 0x04,
	0x01, 0xff, 0xff, 0xff, 0x04, 0xf8, 0x7f, 0xef, 0xff, 0x0b, 0x07, 0x8b, 0xff, 0x02, 0x0c, 0x00,
	0x7f, 0x74, 0x1f, 0x08, 0x00, 0x00, 0xff, 0xf0, 0x07, 0x00, 0x00, 0x0f, 0xc0, 0x71, 0x00, 0x00,
	0x10, 0x38, 0x02, 0x80, 0x00, 0x2f, 0x8c, 0x5e, 0x80, 0x00, 0x60, 0x72, 0xe4, 0x80, 0x00, 0x40,
	0x99, 0x85, 0x00, 0x00, 0x43, 0x79, 0x09, 0x00, 0x00, 0x45, 0xfc, 0x0a, 0x00, 0x00, 0x4b, 0xb4,
	0x12, 0x00, 0x00, 0x2f, 0x94, 0x92, 0x00, 0x00, 0x2f, 0x12, 0xe4, 0x00, 0x01, 0x17, 0x9a, 0xd8,
	0x00, 0x00, 0x17, 0x89, 0xa8, 0x00, 0x00, 0x0f, 0xdd, 0x90, 0x00, 0x01, 0x05, 0xfc, 0x60, 0x00,
	0x00, 0x03, 0xfc, 0xa0, 0x00, 0x21, 0x01, 0x7e, 0xc0, 0x00, 0x09, 0x00, 0xef, 0x40, 0x00, 0x05,
	0x40, 0x3f, 0x80, 0x00, 0x03, 0x80, 0x0b, 0x00, 0x05, 0xbe, 0xea, 0x45, 0x00, 0x00, 0x01, 0x80,
	0x02, 0x00, 0x00, 0x03, 0x40, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x31, 0x10, 0x01,
	0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x0f, 0x79, 0x00, 0x00, 0x00, 0x77, 0xb7, 0x00, 0x00, 0x0f,
	0x98, 0xb3, 0x00, 0x09, 0xf0, 0x26, 0x6a, 0x00, 0x01, 0x02, 0xbc, 0x4a, 0x00, 0x09, 0xa7, 0xfd,
	0x84, 0x00, 0x82, 0xf9, 0xf7, 0x18, 0x00, 0x0b, 0xe1, 0xbc, 0x70, 0x00, 0x2a, 0x8f, 0xf0, 0xc0,
	0x00, 0x1a, 0xff, 0xe3, 0x00, 0x05, 0xf4, 0xff, 0x8c, 0x00, 0x00, 0x1c, 0xec, 0xf0, 0x00, 0x00,
	0x2c, 0xff, 0x00, 0x00, 0x00, 0x4c, 0xe0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x09,
	0x00, 0x00, 0x01, 0x00, 0x0f, 0x40, 0x0e, 0x00, 0x00, 0x30, 0x00, 0x11, 0xc1, 0x10, 0x4f, 0x48,
	0x2c, 0x31, 0x00, 0x70, 0x50, 0x43, 0x89, 0x40, 0x80, 0x2d, 0x40, 0x75, 0x80, 0x83, 0xd0, 0x81,
	0x92, 0xea, 0x87, 0xc0, 0x87, 0x8b, 0x80, 0x47, 0x80, 0x9f, 0xcb, 0x00, 0x4d, 0x41, 0x3d, 0xcb,
	0x20, 0x2e, 0x41, 0x7d, 0x93, 0x00, 0x3e, 0x42, 0xf7, 0x95, 0x00, 0x16, 0x27, 0xe7, 0xa4, 0x00,
	0x0e, 0x95, 0xcf, 0x29, 0x00, 0x05, 0x4f, 0xdf, 0x48, 0x00, 0x02, 0x6f, 0xfe, 0x91, 0x00, 0x01,
	0xfb, 0xff, 0xa0, 0x00, 0x00, 0xdf, 0xfb, 0x40, 0x00, 0x00, 0xff, 0xb6, 0x80, 0x00, 0x00, 0xbf,
	0xa4, 0x80, 0x00, 0x40, 0xdb, 0x45, 0x00, 0x00, 0x00, 0x58, 0x05, 0x00, 0x00, 0x40, 0x00, 0x0a,
	0x00, 0x00, 0x00, 0x04, 0x0a, 0x00, 0x04, 0x42, 0x80, 0x8a, 0x00, 0x00, 0x47, 0x80, 0x01, 0x00,
	0x01, 0x4f, 0x80, 0x25, 0x00, 0x00, 0xf7, 0x52, 0x45, 0x01, 0x5f, 0xaf, 0x41, 0xa8, 0x80, 0x00,
	0x3f, 0x56, 0xf2, 0x80, 0x01, 0x5f, 0xfb, 0xb6, 0x80, 0x02, 0xbb, 0xff, 0xfa, 0x40, 0x00, 0xbf,
	0xe6, 0xfd, 0x40, 0x09, 0x6f, 0xcf, 0xf9, 0x40, 0x01, 0x5d, 0xe7, 0xf8, 0x80, 0x01, 0x1f, 0x7f,
	0xf1, 0x00, 0x02, 0x17, 0x12, 0x8e, 0x00, 0x02, 0x0f, 0x00, 0x1c, 0x00, 0x02, 0x04, 0x03, 0xe0,
	0x00, 0x03, 0x01, 0xfc, 0x00, 0x00, 0x01, 0xfe, 0xf0, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x3e,
	0xa8, 0x00, 0xec, 0x00, 0x41, 0xf0, 0x00, 0x72, 0x00, 0xbc, 0xdf, 0x60, 0xca, 0x01, 0x03, 0x30,
	0x00, 0xc9, 0x02, 0x60, 0xa8, 0x00, 0xe5, 0x04, 0xf0, 0xa0, 0x00, 0xf4, 0x85, 0xcc, 0xa2, 0x00,
	0xfa, 0x4f, 0xce, 0x20, 0x00, 0x7f, 0x5b, 0x8d, 0x40, 0x00, 0x7b, 0x3f, 0x9e, 0x40, 0x00, 0x7f,
	0xbf, 0xba, 0xa0, 0x00, 0xdb, 0xfd, 0x74, 0xa0, 0x00, 0xbf, 0xb7, 0xf5, 0x00, 0x00, 0x4d, 0xf7,
	0x49, 0x20, 0x00, 0x19, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x54, 0xb2, 0x00, 0x00, 0x42, 0x01, 0x2c,
	0x00, 0x00, 0x20, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x40, 0x10, 0xc5, 0x00,
	0x00, 0xa1, 0x04, 0x24, 0x80, 0x00, 0x02, 0x00, 0x2a, 0x40, 0x00, 0x74, 0x20, 0x6b, 0x40, 0x00,
	0x69, 0x59, 0x5f, 0x21, 0x00, 0xad, 0x5b, 0xde, 0xa0, 0x00, 0xfd, 0xaf, 0xf7, 0x91, 0x00, 0x6f,
	0x27, 0x73, 0x50, 0x00, 0xff, 0x47, 0xfb, 0xc9, 0x00, 0xde, 0x85, 0xb9, 0xa9, 0x10, 0xbd, 0x03,
	0xbc, 0xa5, 0x00, 0x3d, 0x02, 0xfc, 0xd5, 0x40, 0x3a, 0x02, 0xdc, 0xd5, 0x80, 0xba, 0x01, 0x5c,
	0xd2, 0xf5, 0xf4, 0x01, 0x3c, 0xcb, 0x80, 0x68, 0x00, 0x8b, 0xcd, 0x00, 0xb0, 0x00, 0x82, 0x89,
	0x20, 0xc0, 0x00, 0x80, 0x10, 0x00, 0x80, 0x00, 0x40, 0xe1, 0x00, 0x00, 0x00, 0x3f, 0x01, 0x00,
	0x47, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x47, 0x47, 0x47, 0x47, 0x47, 0x07, 0x47, 0x47,
	0x47, 0x47, 0x47, 0x07, 0x47, 0x47, 0x07, 0x07, 0x47, 0x07, 0x47, 0x07, 0x47, 0x47, 0x47, 0x07,
	0x07, 0x47, 0x07, 0x07, 0x47, 0x47, 0x07, 0x07, 0x05, 0x45, 0x47, 0x47, 0x47, 0x07, 0x45, 0x47,
	0x07, 0x47, 0x07, 0x07, 0x07, 0x07, 0x47, 0x07, 0x47, 0x07, 0x07, 0x07, 0x05, 0x45, 0x45, 0x45,
	0x05, 0x05, 0x45, 0x05, 0x45, 0x45, 0x05, 0x05, 0x05, 0x05, 0x45, 0x45, 0x45, 0x45, 0x05, 0x07,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x45, 0x45, 0x05, 0x45, 0x45, 0x05, 0x45, 0x45, 0x05,
	0x45, 0x05, 0x45, 0x07, 0x78, 0x41, 0xa6, 0xe6, 0x66, 0x00, 0x78, 0x41, 0x9e, 0xde, 0x5e, 0x00,
	0xfe, 0x42, 0x9e, 0xde, 0x5e, 0x00, 0xfe, 0x42, 0x96, 0xd6, 0x56, 0x00, 0x82, 0x43, 0x9e, 0xde,
	0x5e, 0x00, 0x82, 0x43, 0x96, 0xd6, 0x56, 0x00, 0xac, 0x46, 0xa6, 0xe6, 0x66, 0x00, 0xac, 0x46,
	0x9e, 0xde, 0x5e, 0x00, 0xdb, 0x48, 0xbe, 0xfe, 0x7e, 0x00, 0xdb, 0x48, 0xb6, 0xf6, 0x76, 0x00,
	0xe8, 0x49, 0xa6, 0xe6, 0x66, 0x00, 0xe8, 0x49, 0x9e, 0xde, 0x5e, 0x00, 0x25, 0x4e, 0xbe, 0xfe,
	0x7e, 0x00, 0x25, 0x4e, 0xb6, 0xf6, 0x76, 0x00, 0x53, 0x4e, 0xbe, 0xfe, 0x7e, 0x00, 0x53, 0x4e,
	0xb6, 0xf6, 0x76, 0x00, 0x8e, 0x56, 0x8e, 0xce, 0x4e, 0x00, 0x8e, 0x56, 0x86, 0xc6, 0x46, 0x00,
	0xa1, 0x56, 0xa6, 0xe6, 0x66, 0x00, 0xa1, 0x56, 0x9e, 0xde, 0x5e, 0x00, 0x78, 0x42, 0xa6, 0xe6,
	0x66, 0x00, 0x78, 0x42, 0x9e, 0xde, 0x5e, 0x00, 0xfe, 0x43, 0x9e, 0xde, 0x5e, 0x00, 0xfe, 0x43,
	0x96, 0xd6, 0x56, 0x00, 0x82, 0x44, 0x9e, 0xde, 0x5e, 0x00, 0x82, 0x44, 0x96, 0xd6, 0x56, 0x00,
	0xac, 0x47, 0xa6, 0xe6, 0x66, 0x00, 0xac, 0x47, 0x9e, 0xde, 0x5e, 0x00, 0xdb, 0x49, 0xbe, 0xfe,
	0x7e, 0x00, 0xdb, 0x49, 0xb6, 0xf6, 0x76, 0x00, 0xe8, 0x4a, 0xa6, 0xe6, 0x66, 0x00, 0xe8, 0x4a,
	0x9e, 0xde, 0x5e, 0x00, 0x25, 0x4f, 0xbe, 0xfe, 0x7e, 0x00, 0x25, 0x4f, 0xb6, 0xf6, 0x76, 0x00,
	0x53, 0x4f, 0xbe, 0xfe, 0x7e, 0x00, 0x53, 0x4f, 0xb6, 0xf6, 0x76, 0x00, 0x8e, 0x57, 0x8e, 0xce,
	0x4e, 0x00, 0x8e, 0x57, 0x86, 0xc6, 0x46, 0x00, 0xa1, 0x57, 0xa6, 0xe6, 0x66, 0x00, 0xa1, 0x57,
	0x9e, 0xde, 0x5e, 0x00, 0xad, 0x43, 0x8e, 0xce, 0x4e, 0x00, 0xe2, 0x43, 0xb6, 0xf6, 0x76, 0x00,
	0xea, 0x43, 0xa6, 0xe6, 0x66, 0x00, 0x46, 0x44, 0xbe, 0xfe, 0x7e, 0x00, 0x2f, 0x48, 0x86, 0xc6,
	0x46, 0x00, 0xa7, 0x49, 0x9e, 0xde, 0x5e, 0x00, 0xea, 0x49, 0x8e, 0xce, 0x4e, 0x00, 0x6c, 0x4a,
	0xb6, 0xf6, 0x76, 0x00, 0xb4, 0x4b, 0x8e, 0xce, 0x4e, 0x00, 0xe3, 0x4b, 0x86, 0xc6, 0x46, 0x00,
	0x3a, 0x4d, 0xbe, 0xfe, 0x7e, 0x00, 0x80, 0x4d, 0x96, 0xd6, 0x56, 0x00, 0x9d, 0x4d, 0x86, 0xc6,
	0x46, 0x00, 0xb0, 0x4d, 0x96, 0xd6, 0x56, 0x00, 0xd2, 0x52, 0x86, 0xc6, 0x46, 0x00, 0x2d, 0x53,
	0xae, 0xee, 0x6e, 0x00, 0x32, 0x53, 0x9e, 0xde, 0x5e, 0x00, 0x17, 0x54, 0xa6, 0xe6, 0x66, 0x00,
	0x9c, 0x55, 0xb6, 0xf6, 0x76, 0x00, 0x89, 0x57, 0xb6, 0xf6, 0x76, 0x00, 0x2c, 0x40, 0x06, 0x48,
	0xd4, 0x78, 0x49, 0x50, 0x07, 0x06, 0x46, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0xc3, 0x59, 0xeb, 0xc3, 0xda, 0xeb, 0xc3, 0x44, 0xed, 0xf3, 0x2a, 0x35, 0xf0, 0x22, 0x60, 0xec,
	0x2a, 0x37, 0xf0, 0x22, 0x74, 0xec, 0x2a, 0x39, 0xf0, 0x22, 0x88, 0xec, 0x3e, 0x01, 0x32, 0x62,
	0xec, 0x32, 0x76, 0xec, 0x32, 0x8a, 0xec, 0x3e, 0x08, 0x32, 0x63, 0xec, 0x32, 0x77, 0xec, 0x32,
	0x8b, 0xec, 0x21, 0x20, 0xec, 0x11, 0x20, 0x00, 0x22, 0xfa, 0xeb, 0x19, 0x22, 0xfc, 0xeb, 0x19,
	0x22, 0xfe, 0xeb, 0x21, 0x00, 0x00, 0x22, 0x6e, 0xec, 0x22, 0x82, 0xec, 0x22, 0x96, 0xec, 0x22,
	0x70, 0xec, 0x22, 0x84, 0xec, 0x22, 0x98, 0xec, 0xaf, 0x32, 0xf4, 0xeb, 0xc9, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0xff, 0x16, 0x07, 0xcd, 0x9b,
	0xed, 0xcd, 0x85, 0xed, 0x00, 0xc9, 0xe3, 0xff, 0xf6, 0x03, 0xbd, 0x00, 0x0d, 0xff, 0x0a, 0x0d,
	0x0a, 0x00, 0x00, 0x00, 0x0d, 0x03, 0x4f, 0x69, 0x5c, 0xc4, 0x16, 0xc4, 0x3c, 0xc4, 0x5c, 0xc4,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xc7, 0x1c, 0xd8, 0x94, 0xc7, 0x94, 0xc7,
	0x16, 0x95, 0xd7, 0xc7, 0xb5, 0xc6, 0x68, 0xaa, 0x5a, 0xaa, 0xfe, 0x07, 0x58, 0xaa, 0xfe, 0x06,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xc7, 0x1c, 0xd8,
	0x94, 0xc7, 0xb5, 0xc6, 0xb5, 0xc6, 0x63, 0x8c, 0x94, 0xc7, 0xb5, 0xc6, 0x05, 0xab, 0xe6, 0x02,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xc7, 0x94, 0xc7, 0x00, 0x94,
	0x94, 0xc7, 0x94, 0xc7, 0x57, 0x89, 0x94, 0xc7, 0x57, 0x89, 0xb5, 0xc6, 0xc5, 0xab, 0xe6, 0x02,
	0xfa, 0xaa, 0x05, 0x01, 0xd4, 0xaa, 0x01, 0xe3, 0xff, 0x0a, 0xcc, 0xaa, 0x05, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x4d, 0x0f, 0x09, 0xab, 0x0f, 0x08, 0x9d, 0xab, 0x01, 0xf6, 0x03, 0x0d, 0x97, 0xab,
	0xa7, 0xab, 0x00, 0x00, 0xa2, 0xab, 0x19, 0x08, 0xcf, 0xab, 0x05, 0x08, 0xd0, 0xad, 0x01, 0xbd,
	0x00, 0x0a, 0xc4, 0xad, 0xda, 0xad, 0x00, 0x00, 0xd5, 0xad, 0x36, 0x04, 0xbf, 0x0f, 0xdc, 0x0e,
	0x07, 0x0e, 0x3d, 0x0d, 0x7f, 0x0c, 0xcc, 0x0b, 0x22, 0x0b, 0x82, 0x0a, 0xeb, 0x09, 0x5d, 0x09,
	0xd6, 0x08, 0x57, 0x08, 0xdf, 0x07, 0x6e, 0x07, 0x03, 0x07, 0x9f, 0x06, 0x40, 0x06, 0xe6, 0x05,
	0x91, 0x05, 0x41, 0x05, 0xf6, 0x04, 0xae, 0x04, 0x6b, 0x04, 0x2c, 0x04, 0xf0, 0x03, 0xb7, 0x03,
	0x82, 0x03, 0x4f, 0x03, 0x20, 0x03, 0xf3, 0x02, 0xc8, 0x02, 0xa1, 0x02, 0x7b, 0x02, 0x57, 0x02,
	0x36, 0x02, 0x16, 0x02, 0xf8, 0x01, 0xdc, 0x01, 0xc1, 0x01, 0xa8, 0x01, 0x90, 0x01, 0x79, 0x01,
	0x64, 0x01, 0x50, 0x01, 0x3d, 0x01, 0x2c, 0x01, 0x1b, 0x01, 0x0b, 0x01, 0xfc, 0x00, 0xee, 0x00,
	0xe0, 0x00, 0xd4, 0x00, 0xc8, 0x00, 0xbd, 0x00, 0xb2, 0x00, 0xa8, 0x00, 0x9f, 0x00, 0x96, 0x00,
	0x8d, 0x00, 0x85, 0x00, 0x7e, 0x00, 0x77, 0x00, 0x70, 0x00, 0x6a, 0x00, 0x64, 0x00, 0x5e, 0x00,
	0x59, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x43, 0x00, 0x3f, 0x00, 0x3b, 0x00,
	0x38, 0x00, 0x35, 0x00, 0x32, 0x00, 0x2f, 0x00, 0x2d, 0x00, 0x2a, 0x00, 0x28, 0x00, 0x25, 0x00,
	0x23, 0x00, 0x21, 0x00, 0xdd, 0x21, 0x60, 0xec, 0x2a, 0xfa, 0xeb, 0x3e, 0x01, 0xcd, 0xb0, 0xed,
	0x22, 0xfa, 0xeb, 0xdd, 0x21, 0x74, 0xec, 0x2a, 0xfc, 0xeb, 0x3e, 0x02, 0xcd, 0xb0, 0xed, 0x22,
	0xfc, 0xeb, 0xdd, 0x21, 0x88, 0xec, 0x2a, 0xfe, 0xeb, 0x3e, 0x03, 0xcd, 0xb0, 0xed, 0x22, 0xfe,
	0xeb, 0x3a, 0x8b, 0xec, 0x07, 0x47, 0x3a, 0x77, 0xec, 0xb0, 0x07, 0x47, 0x3a, 0x63, 0xec, 0xb0,
	0x16, 0x07, 0xcd, 0x9b, 0xed, 0x16, 0x0d, 0x21, 0xf3, 0xeb, 0x7a, 0x01, 0xfd, 0xff, 0xed, 0x79,
	0x7e, 0x06, 0xbf, 0xed, 0x79, 0x2b, 0x15, 0xf2, 0x8a, 0xed, 0xc9, 0x01, 0xe6, 0xeb, 0x6a, 0x26,
	0x00, 0x09, 0x77, 0xc9, 0xed, 0x73, 0xf8, 0xeb, 0x2a, 0xf8, 0xeb, 0xed, 0x7b, 0xf6, 0xeb, 0xc9,
	0xed, 0x73, 0xf6, 0xeb, 0xf9, 0x32, 0xf5, 0xeb, 0xdd, 0x35, 0x02, 0xca, 0xbf, 0xee, 0xdd, 0x35,
	0x06, 0x20, 0x36, 0xdd, 0x6e, 0x04, 0xdd, 0x66, 0x05, 0x7e, 0xfe, 0x80, 0x20, 0x0c, 0x23, 0x5e,
	0x23, 0x56, 0xdd, 0x73, 0x04, 0xdd, 0x72, 0x05, 0x18, 0xe9, 0xfe, 0x1e, 0x38, 0x0c, 0xd6, 0x32,
	0xdd, 0x77, 0x09, 0xdd, 0x36, 0x06, 0x01, 0x23, 0x18, 0x09, 0xdd, 0x77, 0x09, 0x23, 0x7e, 0xdd,
	0x77, 0x06, 0x23, 0xdd, 0x75, 0x04, 0xdd, 0x74, 0x05, 0xdd, 0x7e, 0x07, 0xdd, 0xb6, 0x08, 0xca,
	0x82, 0xee, 0xdd, 0xcb, 0x0e, 0x56, 0xc2, 0x82, 0xee, 0xdd, 0x6e, 0x0c, 0xdd, 0x66, 0x0d, 0x7e,
	0x23, 0xdd, 0x75, 0x0c, 0xdd, 0x74, 0x0d, 0xfe, 0x80, 0x20, 0x06, 0x7e, 0x23, 0x66, 0x6f, 0x18,
	0xee, 0xfe, 0x82, 0xc2, 0x2d, 0xee, 0xdd, 0xcb, 0x0e, 0xde, 0xc3, 0x0f, 0xee, 0xfe, 0x83, 0xc2,
	0x39, 0xee, 0xdd, 0xcb, 0x0e, 0x9e, 0xc3, 0x0f, 0xee, 0xfe, 0x84, 0xc2, 0x49, 0xee, 0x3e, 0x09,
	0xdd, 0xae, 0x03, 0xdd, 0x77, 0x03, 0xc3, 0x0f, 0xee, 0xdd, 0xcb, 0x0e, 0x5e, 0xca, 0x6b, 0xee,
	0xdd, 0x86, 0x12, 0xdd, 0x77, 0x12, 0x3d, 0x87, 0x5f, 0x16, 0x00, 0x21, 0x9c, 0xec, 0x19, 0x7e,
	0xdd, 0x77, 0x07, 0x23, 0x7e, 0xdd, 0x77, 0x08, 0xc3, 0x82, 0xee, 0x5f, 0x16, 0x00, 0xdd, 0x6e,
	0x07, 0xdd, 0x66, 0x08, 0xe6, 0x80, 0xca, 0x7b, 0xee, 0x16, 0xff, 0x19, 0xdd, 0x75, 0x07, 0xdd,
	0x74, 0x08, 0x3a, 0xf4, 0xeb, 0x16, 0x06, 0xcd, 0x9b, 0xed, 0xdd, 0xcb, 0x0e, 0x96, 0x3a, 0xf5,
	0xeb, 0xc6, 0x07, 0x57, 0xdd, 0x7e, 0x07, 0xdd, 0xb6, 0x08, 0x28, 0x03, 0xdd, 0x7e, 0x09, 0xcd,
	0x9b, 0xed, 0x3a, 0xf5, 0xeb, 0x3d, 0x87, 0x57, 0xdd, 0x7e, 0x07, 0xcd, 0x9b, 0xed, 0x14, 0xdd,
	0x7e, 0x08, 0xcd, 0x9b, 0xed, 0xc3, 0xa4, 0xed, 0xdd, 0x75, 0x00, 0xdd, 0x74, 0x01, 0xc9, 0xdd,
	0x6e, 0x00, 0xdd, 0x66, 0x01, 0x7e, 0x23, 0xcd, 0xb8, 0xee, 0xcb, 0x7f, 0xc2, 0x3c, 0xef, 0x22,
	0xf8, 0xeb, 0xb7, 0x28, 0x1b, 0xdd, 0x86, 0x0f, 0xdd, 0x77, 0x12, 0xdd, 0xcb, 0x0e, 0x9e, 0x3d,
	0x87, 0x5f, 0x16, 0x00, 0x21, 0x9c, 0xec, 0x19, 0x5e, 0x23, 0x56, 0x2a, 0xf8, 0xeb, 0x18, 0x03,
	0x11, 0x00, 0x00, 0x7e, 0x23, 0xcd, 0xb8, 0xee, 0xdd, 0x77, 0x02, 0xdd, 0x73, 0x07, 0xdd, 0x72,
	0x08, 0xdd, 0x7e, 0x10, 0xdd, 0x77, 0x0c, 0xdd, 0x7e, 0x11, 0xdd, 0x77, 0x0d, 0xdd, 0xcb, 0x0e,
	0xd6, 0xdd, 0xcb, 0x0e, 0x4e, 0xc2, 0xbe, 0xed, 0xdd, 0xcb, 0x0e, 0x46, 0xca, 0x23, 0xef, 0xdd,
	0xcb, 0x0e, 0xce, 0xdd, 0x4e, 0x0a, 0xdd, 0x46, 0x0b, 0x0a, 0xdd, 0x77, 0x09, 0x03, 0x0a, 0x03,
	0xdd, 0x77, 0x06, 0xdd, 0x71, 0x04, 0xdd, 0x70, 0x05, 0xc3, 0x82, 0xee, 0xe6, 0x7f, 0x22, 0xf8,
	0xeb, 0x87, 0x5f, 0x16, 0x00, 0x21, 0x52, 0xef, 0x19, 0x7e, 0x23, 0x66, 0x6f, 0xe5, 0x2a, 0xf8,
	0xeb, 0xc9, 0x70, 0xef, 0x7c, 0xef, 0x8a, 0xef, 0x94, 0xef, 0xa6, 0xef, 0xb1, 0xef, 0xde, 0xef,
	0xbc, 0xef, 0xcc, 0xef, 0xd7, 0xef, 0xee, 0xef, 0xfc, 0xef, 0x0a, 0xf0, 0x17, 0xf0, 0x27, 0xf0,
	0x7e, 0xdd, 0x77, 0x00, 0x23, 0x7e, 0xdd, 0x77, 0x01, 0xc3, 0xbf, 0xee, 0x7e, 0xdd, 0x77, 0x00,
	0x23, 0x7e, 0xdd, 0x77, 0x01, 0x23, 0xe5, 0xc3, 0xbf, 0xee, 0x46, 0xc5, 0x23, 0xe5, 0xcd, 0xb8,
	0xee, 0xc3, 0xbf, 0xee, 0xd1, 0xc1, 0x10, 0x03, 0xc3, 0xbf, 0xee, 0xc5, 0xd5, 0xdd, 0x73, 0x00,
	0xdd, 0x72, 0x01, 0xc3, 0xbf, 0xee, 0x7e, 0x23, 0x32, 0xf4, 0xeb, 0xcd, 0xb8, 0xee, 0xc3, 0xbf,
	0xee, 0x7e, 0x23, 0xcd, 0xb8, 0xee, 0xdd, 0x77, 0x03, 0xc3, 0xbf, 0xee, 0x7e, 0xdd, 0x77, 0x0a,
	0x23, 0x7e, 0xdd, 0x77, 0x0b, 0x23, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x7e, 0x23, 0xcd, 0xb8,
	0xee, 0xdd, 0x77, 0x0f, 0xc3, 0xbf, 0xee, 0xe1, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x7e, 0xdd,
	0x77, 0x10, 0x23, 0x7e, 0xdd, 0x77, 0x11, 0x23, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0xdd, 0xcb,
	0x0e, 0xc6, 0xdd, 0xcb, 0x0e, 0x8e, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0xdd, 0xcb, 0x0e, 0x86,
	0xdd, 0xcb, 0x0e, 0x8e, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x5e, 0x23, 0x56, 0x23, 0xcd, 0xb8,
	0xee, 0x01, 0xbf, 0xee, 0xc5, 0xd5, 0xc9, 0x3a, 0xf4, 0xeb, 0x86, 0xe6, 0x0f, 0x32, 0xf4, 0xeb,
	0x23, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x7e, 0xdd, 0x86, 0x0f, 0xdd, 0x77, 0x0f, 0x23, 0xcd,
	0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x99, 0xf5, 0x96, 0xf4, 0x3b, 0xf0, 0x82, 0x04, 0x81, 0x57, 0xf4,
	0x83, 0x81, 0x6d, 0xf3, 0x81, 0x6d, 0xf3, 0x81, 0x00, 0xf4, 0x81, 0x33, 0xf3, 0x81, 0x33, 0xf3,
	0x81, 0x17, 0xf3, 0x81, 0x6a, 0xf2, 0x81, 0x6a, 0xf2, 0x88, 0x00, 0x81, 0xba, 0xf2, 0x81, 0xba,
	0xf2, 0x88, 0x02, 0x81, 0xba, 0xf2, 0x88, 0x00, 0x81, 0xef, 0xf2, 0x82, 0x04, 0x81, 0x49, 0xf2,
	0x83, 0x81, 0x17, 0xf3, 0x81, 0x49, 0xf2, 0x81, 0x49, 0xf2, 0x81, 0x1a, 0xf3, 0x81, 0x49, 0xf2,
	0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x2b, 0x23, 0x86, 0x9b, 0xf7, 0x2b, 0x0c, 0x86, 0x5e, 0xf7,
	0x2d, 0x48, 0x2b, 0x0c, 0x2d, 0x0c, 0x32, 0x0c, 0x30, 0x0c, 0x2d, 0x18, 0x30, 0x24, 0x86, 0x9b,
	0xf7, 0x30, 0x0c, 0x86, 0x5e, 0xf7, 0x32, 0x48, 0x32, 0x0c, 0x37, 0x0c, 0x36, 0x0c, 0x32, 0x0c,
	0x2d, 0x18, 0x2b, 0x24, 0x86, 0x9b, 0xf7, 0x2b, 0x0c, 0x86, 0x5e, 0xf7, 0x2d, 0x48, 0x32, 0x0c,
	0x86, 0x97, 0xf7, 0x32, 0x0c, 0x86, 0x5e, 0xf7, 0x32, 0x0c, 0x30, 0x0c, 0x2d, 0x18, 0x32, 0x24,
	0x86, 0x97, 0xf7, 0x32, 0x0c, 0x86, 0x5e, 0xf7, 0x30, 0x48, 0x32, 0x0c, 0x34, 0x0c, 0x37, 0x0c,
	0x36, 0x0c, 0x37, 0x0c, 0x39, 0x0c, 0x37, 0x24, 0x86, 0x9b, 0xf7, 0x37, 0x0c, 0x86, 0x5e, 0xf7,
	0x39, 0x30, 0x37, 0x06, 0x39, 0x0c, 0x37, 0x06, 0x39, 0x0c, 0x37, 0x06, 0x36, 0x0c, 0x37, 0x06,
	0x36, 0x0c, 0x34, 0x0c, 0x32, 0x0c, 0x30, 0x06, 0x32, 0x0c, 0x30, 0x06, 0x32, 0x0c, 0x30, 0x06,
	0x2f, 0x0c, 0x30, 0x06, 0x2f, 0x0c, 0x2d, 0x0c, 0x2b, 0x0c, 0x2d, 0x06, 0x2d, 0x0c, 0x2b, 0x06,
	0x2d, 0x0c, 0x2f, 0x06, 0x30, 0x0c, 0x32, 0x06, 0x34, 0x0c, 0x36, 0x0c, 0x37, 0x0c, 0x3b, 0x24,
	0x86, 0x97, 0xf7, 0x3b, 0x0c, 0x86, 0x5e, 0xf7, 0x39, 0x48, 0x37, 0x0c, 0x39, 0x0c, 0x3c, 0x06,
	0x3c, 0x06, 0x39, 0x0c, 0x3e, 0x0c, 0x3c, 0x0c, 0x40, 0x24, 0x86, 0x97, 0xf7, 0x40, 0x0c, 0x86,
	0x5e, 0xf7, 0x3e, 0x60, 0x00, 0x06, 0x3e, 0x06, 0x3e, 0x06, 0x40, 0x06, 0x41, 0x06, 0x40, 0x06,
	0x3c, 0x06, 0x3e, 0x07, 0x81, 0xd9, 0xf1, 0x81, 0x11, 0xf2, 0x82, 0x02, 0x3d, 0x0b, 0x36, 0x0c,
	0x3b, 0x0c, 0x36, 0x06, 0x3a, 0x0c, 0x36, 0x06, 0x38, 0x0c, 0x36, 0x06, 0x36, 0x06, 0x3b, 0x06,
	0x3d, 0x06, 0x3d, 0x06, 0x3d, 0x06, 0x36, 0x0c, 0x3b, 0x0c, 0x36, 0x06, 0x3a, 0x0c, 0x36, 0x06,
	0x38, 0x0c, 0x36, 0x06, 0x36, 0x06, 0x3b, 0x06, 0x3d, 0x07, 0x83, 0x81, 0x6a, 0xf2, 0x81, 0x49,
	0xf2, 0x81, 0xc3, 0xf1, 0x81, 0x1a, 0xf3, 0x81, 0x4c, 0xf2, 0x81, 0xba, 0xf2, 0x81, 0x4c, 0xf2,
	0x88, 0x02, 0x81, 0xba, 0xf2, 0x88, 0x00, 0x81, 0xef, 0xf2, 0x81, 0x4c, 0xf2, 0x81, 0xc3, 0xf1,
	0x80, 0x3b, 0xf0, 0x87, 0xff, 0xf6, 0x46, 0x18, 0x00, 0x30, 0x87, 0x33, 0xf7, 0x86, 0x1b, 0xf7,
	0x28, 0x0b, 0x00, 0x01, 0x28, 0x0b, 0x00, 0x01, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x82,
	0x02, 0x40, 0x0b, 0x39, 0x0c, 0x3e, 0x0c, 0x39, 0x06, 0x3c, 0x0c, 0x39, 0x06, 0x3b, 0x0c, 0x3c,
	0x06, 0x39, 0x06, 0x3c, 0x06, 0x3e, 0x06, 0x40, 0x06, 0x40, 0x06, 0x39, 0x0c, 0x3e, 0x0c, 0x39,
	0x06, 0x3c, 0x0c, 0x39, 0x06, 0x3b, 0x0c, 0x3c, 0x06, 0x39, 0x06, 0x3c, 0x06, 0x3e, 0x07, 0x83,
	0x89, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x82, 0x02, 0x40, 0x0b, 0x39, 0x0c, 0x3f, 0x0c, 0x39,
	0x06, 0x3d, 0x0c, 0x3d, 0x06, 0x3b, 0x0c, 0x3d, 0x06, 0x39, 0x06, 0x3d, 0x06, 0x3f, 0x06, 0x40,
	0x06, 0x40, 0x06, 0x39, 0x0c, 0x3f, 0x0c, 0x39, 0x06, 0x3d, 0x0c, 0x3d, 0x06, 0x3b, 0x0c, 0x3d,
	0x06, 0x39, 0x06, 0x3d, 0x06, 0x3f, 0x07, 0x83, 0x89, 0x81, 0x4c, 0xf2, 0x86, 0x45, 0xf7, 0x87,
	0x9f, 0xf7, 0x82, 0x04, 0x46, 0x06, 0x83, 0x46, 0x0c, 0x44, 0x06, 0x46, 0x0a, 0x00, 0x02, 0x44,
	0x06, 0x46, 0x0a, 0x00, 0x02, 0x46, 0x0c, 0x44, 0x0c, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7,
	0x36, 0x23, 0x86, 0x97, 0xf7, 0x36, 0x0c, 0x86, 0x5e, 0xf7, 0x34, 0x18, 0x31, 0x0c, 0x2f, 0x18,
	0x2e, 0x0c, 0x2e, 0x0c, 0x81, 0xef, 0xf3, 0x8e, 0xfd, 0x81, 0xef, 0xf3, 0x8e, 0x03, 0x87, 0x4f,
	0xf7, 0x86, 0x5e, 0xf7, 0x2e, 0x0c, 0x2f, 0x0c, 0x31, 0x0c, 0x31, 0x12, 0x31, 0x12, 0x31, 0x0c,
	0x34, 0x12, 0x31, 0x12, 0x2f, 0x0c, 0x31, 0x18, 0x86, 0x97, 0xf7, 0x31, 0x30, 0x81, 0xef, 0xf3,
	0x8e, 0xfd, 0x81, 0xef, 0xf3, 0x00, 0x01, 0x8e, 0x03, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7,
	0x32, 0x18, 0x81, 0xef, 0xf3, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x32, 0x06, 0x32, 0x06, 0x34,
	0x12, 0x32, 0x12, 0x30, 0x0c, 0x32, 0x18, 0x81, 0xef, 0xf3, 0x8e, 0xfb, 0x81, 0xef, 0xf3, 0x81,
	0x87, 0xf5, 0x86, 0x1b, 0xf7, 0x87, 0x33, 0xf7, 0x8e, 0x05, 0x2b, 0x0c, 0x28, 0x0c, 0x89, 0x87,
	0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x34, 0x18, 0x81, 0xef, 0xf3, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7,
	0x34, 0x06, 0x34, 0x06, 0x36, 0x12, 0x34, 0x12, 0x32, 0x0c, 0x34, 0x12, 0x36, 0x12, 0x38, 0x0c,
	0x36, 0x12, 0x38, 0x12, 0x39, 0x0c, 0x89, 0x81, 0x1a, 0xf3, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7,
	0x82, 0x02, 0x82, 0x02, 0x30, 0x06, 0x2f, 0x0c, 0x2e, 0x06, 0x2d, 0x0c, 0x83, 0x30, 0x0c, 0x32,
	0x0c, 0x83, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x7c, 0xf7, 0x82, 0x04, 0x30, 0x06, 0x2f, 0x0c, 0x2e,
	0x06, 0x2d, 0x0c, 0x83, 0x30, 0x06, 0x2f, 0x0c, 0x2d, 0x06, 0x35, 0x0c, 0x34, 0x0c, 0x82, 0x02,
	0x35, 0x06, 0x34, 0x0c, 0x33, 0x06, 0x32, 0x0c, 0x83, 0x35, 0x0c, 0x34, 0x0c, 0x82, 0x02, 0x2f,
	0x06, 0x2e, 0x0c, 0x2d, 0x06, 0x2c, 0x0c, 0x83, 0x30, 0x0c, 0x2f, 0x0c, 0x89, 0x87, 0x4f, 0xf7,
	0x86, 0x5e, 0xf7, 0x88, 0x00, 0x00, 0x05, 0x2d, 0x06, 0x2d, 0x0c, 0x2d, 0x0c, 0x2d, 0x0c, 0x2d,
	0x18, 0x2d, 0x1e, 0x2d, 0x06, 0x34, 0x0c, 0x34, 0x0c, 0x34, 0x0c, 0x34, 0x18, 0x81, 0xef, 0xf3,
	0x00, 0x0c, 0x35, 0x18, 0x34, 0x18, 0x35, 0x18, 0x34, 0x0c, 0x32, 0x12, 0x2f, 0x06, 0x2f, 0x0c,
	0x2f, 0x0c, 0x2f, 0x0c, 0x2f, 0x18, 0x81, 0xef, 0xf3, 0x00, 0x0c, 0x00, 0x06, 0x30, 0x06, 0x30,
	0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x18, 0x30, 0x1e, 0x30, 0x06, 0x37, 0x0c, 0x37, 0x0c, 0x37,
	0x0c, 0x37, 0x18, 0x81, 0xef, 0xf3, 0x00, 0x0c, 0x38, 0x18, 0x37, 0x18, 0x38, 0x18, 0x37, 0x0c,
	0x35, 0x12, 0x32, 0x06, 0x32, 0x0c, 0x32, 0x0c, 0x32, 0x0c, 0x32, 0x18, 0x87, 0x33, 0xf7, 0x86,
	0x1b, 0xf7, 0x00, 0x01, 0x2d, 0x0b, 0x00, 0x01, 0x28, 0x05, 0x00, 0x01, 0x28, 0x06, 0x89, 0x87,
	0x33, 0xf7, 0x86, 0x1b, 0xf7, 0x00, 0x01, 0x2b, 0x0b, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x89,
	0x87, 0x69, 0xf7, 0x84, 0x1f, 0x85, 0x01, 0x82, 0x04, 0x07, 0x06, 0x8d, 0xfe, 0x83, 0x85, 0x08,
	0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x2d, 0x0b, 0x2d, 0x0c, 0x2d, 0x06, 0x2d, 0x06, 0x2d, 0x0c,
	0x2f, 0x0c, 0x30, 0x0c, 0x32, 0x06, 0x32, 0x06, 0x32, 0x0c, 0x32, 0x0c, 0x32, 0x0c, 0x32, 0x18,
	0x81, 0xef, 0xf3, 0x32, 0x06, 0x34, 0x06, 0x35, 0x06, 0x35, 0x06, 0x34, 0x0c, 0x32, 0x0c, 0x30,
	0x0c, 0x2f, 0x0c, 0x2d, 0x0c, 0x2c, 0x1e, 0x2d, 0x06, 0x2d, 0x0c, 0x2d, 0x0c, 0x2f, 0x0c, 0x2d,
	0x18, 0x81, 0xef, 0xf3, 0x00, 0x0d, 0x89, 0x88, 0x07, 0x87, 0x3e, 0xf7, 0x86, 0x45, 0xf7, 0x45,
	0x04, 0x00, 0x02, 0x45, 0x04, 0x00, 0x02, 0x39, 0x0c, 0x87, 0x1f, 0xf7, 0x86, 0x38, 0xf7, 0x2d,
	0x0b, 0x2d, 0x0c, 0x2e, 0x12, 0x2d, 0x12, 0x2b, 0x0c, 0x2b, 0x06, 0x2d, 0x06, 0x2d, 0x06, 0x2d,
	0x06, 0x2d, 0x0c, 0x2b, 0x0c, 0x2d, 0x06, 0x2b, 0x06, 0x2d, 0x0d, 0x87, 0x3e, 0xf7, 0x86, 0x45,
	0xf7, 0x40, 0x0c, 0x39, 0x0c, 0x89, 0x82, 0x04, 0x81, 0x6e, 0xf5, 0x83, 0x81, 0x60, 0xf5, 0x81,
	0x60, 0xf5, 0x82, 0x06, 0x81, 0x6e, 0xf5, 0x83, 0x81, 0x2f, 0xf5, 0x81, 0x2f, 0xf5, 0x8e, 0xf8,
	0x81, 0x2c, 0xf5, 0x81, 0x2c, 0xf5, 0x8e, 0x01, 0x81, 0x2c, 0xf5, 0x8e, 0x02, 0x81, 0x2c, 0xf5,
	0x8e, 0x05, 0x88, 0xf4, 0x82, 0x04, 0x81, 0x49, 0xf2, 0x83, 0x88, 0x00, 0x81, 0x2f, 0xf5, 0x81,
	0x2f, 0xf5, 0x88, 0xf4, 0x81, 0x49, 0xf2, 0x81, 0x49, 0xf2, 0x88, 0x00, 0x81, 0x2f, 0xf5, 0x88,
	0xf4, 0x81, 0x49, 0xf2, 0x88, 0x00, 0x82, 0x08, 0x81, 0x2f, 0xf5, 0x83, 0x81, 0x2c, 0xf5, 0x88,
	0xf8, 0x81, 0x2c, 0xf5, 0x81, 0x2c, 0xf5, 0x81, 0x2c, 0xf5, 0x88, 0xf4, 0x81, 0x49, 0xf2, 0x88,
	0xff, 0x81, 0xc3, 0xf1, 0x88, 0x00, 0x81, 0x2f, 0xf5, 0x81, 0x24, 0xf5, 0x88, 0xf9, 0x81, 0x2f,
	0xf5, 0x81, 0x24, 0xf5, 0x88, 0xfb, 0x81, 0x2c, 0xf5, 0x81, 0x24, 0xf5, 0x81, 0xc3, 0xf1, 0x88,
	0x00, 0x80, 0x96, 0xf4, 0x88, 0xf4, 0x81, 0x4c, 0xf2, 0x88, 0xff, 0x89, 0x81, 0x2f, 0xf5, 0x87,
	0x8c, 0xf7, 0x86, 0x38, 0xf7, 0x43, 0x0c, 0x45, 0x0c, 0x86, 0x84, 0xf7, 0x8e, 0x0c, 0x2d, 0x0c,
	0x2d, 0x0c, 0x2d, 0x24, 0x2b, 0x06, 0x2b, 0x0c, 0x2d, 0x06, 0x2d, 0x0c, 0x2d, 0x0c, 0x2b, 0x0c,
	0x2d, 0x06, 0x2b, 0x06, 0x2d, 0x0c, 0x8e, 0xf4, 0x86, 0x38, 0xf7, 0x43, 0x0c, 0x45, 0x0c, 0x89,
	0x81, 0x6b, 0xf5, 0x8e, 0x03, 0x81, 0x6b, 0xf5, 0x8e, 0xfd, 0x89, 0x81, 0x6e, 0xf5, 0x81, 0x87,
	0xf5, 0x34, 0x0c, 0x34, 0x0c, 0x35, 0x12, 0x34, 0x12, 0x32, 0x0c, 0x81, 0x87, 0xf5, 0x34, 0x0c,
	0x34, 0x0c, 0x34, 0x18, 0x00, 0x18, 0x89, 0x84, 0x0a, 0x85, 0x01, 0x87, 0x69, 0xf7, 0x86, 0x2b,
	0xf7, 0x07, 0x18, 0x85, 0x08, 0x87, 0x1f, 0xf7, 0x89, 0x81, 0xa0, 0xf6, 0x81, 0xa0, 0xf6, 0x81,
	0x95, 0xf6, 0x81, 0x95, 0xf6, 0x81, 0xb6, 0xf6, 0x88, 0x05, 0x81, 0xb6, 0xf6, 0x88, 0xfb, 0x81,
	0xb6, 0xf6, 0x88, 0x00, 0x81, 0xb6, 0xf6, 0x81, 0xa0, 0xf6, 0x81, 0xa0, 0xf6, 0x81, 0xb3, 0xf6,
	0x88, 0x05, 0x81, 0xb3, 0xf6, 0x88, 0xfd, 0x81, 0x8a, 0xf6, 0x81, 0x8a, 0xf6, 0x88, 0x05, 0x81,
	0xb0, 0xf6, 0x88, 0xfb, 0x81, 0xb0, 0xf6, 0x88, 0x00, 0x82, 0x04, 0x81, 0x55, 0xf6, 0x83, 0x81,
	0xb3, 0xf6, 0x88, 0x05, 0x81, 0xb3, 0xf6, 0x88, 0x00, 0x81, 0x55, 0xf6, 0x81, 0x55, 0xf6, 0x81,
	0xb6, 0xf6, 0x88, 0x05, 0x81, 0xb6, 0xf6, 0x88, 0x00, 0x81, 0x55, 0xf6, 0x82, 0x04, 0x88, 0x00,
	0x81, 0xb3, 0xf6, 0x88, 0x05, 0x81, 0xb3, 0xf6, 0x83, 0x88, 0x00, 0x81, 0xb3, 0xf6, 0x88, 0x05,
	0x81, 0xb3, 0xf6, 0x88, 0x04, 0x81, 0xb3, 0xf6, 0x88, 0x00, 0x81, 0xb3, 0xf6, 0x88, 0xfd, 0x81,
	0xb3, 0xf6, 0x88, 0x04, 0x81, 0xb3, 0xf6, 0x88, 0xfd, 0x81, 0x8a, 0xf6, 0x88, 0x00, 0x81, 0x55,
	0xf6, 0x00, 0x60, 0x81, 0xb6, 0xf6, 0x88, 0x05, 0x81, 0xb6, 0xf6, 0x81, 0x58, 0xf6, 0x88, 0x05,
	0x81, 0xb3, 0xf6, 0x81, 0x58, 0xf6, 0x88, 0xfb, 0x81, 0xb0, 0xf6, 0x81, 0x58, 0xf6, 0x00, 0x60,
	0x88, 0x00, 0x80, 0x99, 0xf5, 0x81, 0x58, 0xf6, 0x88, 0x00, 0x86, 0x1b, 0xf7, 0x82, 0x04, 0x81,
	0x76, 0xf6, 0x83, 0x2b, 0x09, 0x00, 0x03, 0x82, 0x06, 0x81, 0x76, 0xf6, 0x83, 0x2b, 0x09, 0x00,
	0x03, 0x27, 0x09, 0x00, 0x03, 0x89, 0x87, 0x33, 0xf7, 0x85, 0x01, 0x84, 0x1c, 0x07, 0x01, 0x00,
	0x01, 0x84, 0x02, 0x07, 0x01, 0x00, 0x03, 0x85, 0x08, 0x89, 0x81, 0xb3, 0xf6, 0x8e, 0x07, 0x81,
	0xb3, 0xf6, 0x8e, 0xf9, 0x89, 0x81, 0xa0, 0xf6, 0x8e, 0x03, 0x81, 0xa0, 0xf6, 0x8e, 0xfd, 0x89,
	0x81, 0xb3, 0xf6, 0x8e, 0x01, 0x81, 0xb6, 0xf6, 0x8e, 0xfa, 0x81, 0xb6, 0xf6, 0x8e, 0x05, 0x89,
	0x81, 0xb3, 0xf6, 0x81, 0xb6, 0xf6, 0x87, 0xeb, 0xf6, 0x86, 0xf4, 0xf6, 0x15, 0x0c, 0x15, 0x06,
	0x21, 0x06, 0x81, 0xd1, 0xf6, 0x15, 0x0c, 0x15, 0x18, 0x81, 0xd1, 0xf6, 0x1f, 0x06, 0x21, 0x06,
	0x89, 0x87, 0xff, 0xf6, 0x84, 0x1f, 0x85, 0x01, 0x8a, 0x82, 0x06, 0x07, 0x01, 0x8d, 0xf0, 0x07,
	0x01, 0x8d, 0x0e, 0x83, 0x8b, 0x85, 0x08, 0x87, 0xeb, 0xf6, 0x89, 0x0f, 0x01, 0x40, 0x3f, 0x0c,
	0xff, 0x80, 0xeb, 0xf6, 0x00, 0x00, 0x05, 0x05, 0x03, 0xfd, 0xfb, 0xfb, 0x80, 0xf4, 0xf6, 0x0f,
	0x01, 0x40, 0x3b, 0x3f, 0x3e, 0x3b, 0x3d, 0x3c, 0x3b, 0x3b, 0x3a, 0x3b, 0x39, 0x38, 0x3b, 0x37,
	0x36, 0x3b, 0x35, 0x34, 0x3b, 0x33, 0x00, 0xff, 0x80, 0xff, 0xf6, 0x32, 0x80, 0x1b, 0xf7, 0x0f,
	0x01, 0x40, 0x3f, 0x3e, 0x3d, 0x3a, 0x0b, 0x02, 0x80, 0x25, 0xf7, 0x82, 0x0c, 0xf4, 0x07, 0xf9,
	0x80, 0x2b, 0xf7, 0x0f, 0xff, 0x80, 0x33, 0xf7, 0x82, 0x0c, 0xf4, 0x80, 0x38, 0xf7, 0x0f, 0x01,
	0x3f, 0x3a, 0x80, 0x3e, 0xf7, 0x82, 0x05, 0x03, 0xf8, 0x05, 0x07, 0xf4, 0x80, 0x45, 0xf7, 0x00,
	0x01, 0x0f, 0x03, 0x0e, 0x04, 0x0d, 0x04, 0x0c, 0x04, 0x0b, 0xff, 0x80, 0x4f, 0xf7, 0x02, 0x01,
	0xff, 0xfe, 0xfe, 0xff, 0x01, 0x02, 0x80, 0x5e, 0xf7, 0x0f, 0x02, 0x00, 0x04, 0x0e, 0x02, 0x00,
	0x04, 0x0d, 0x03, 0x00, 0x03, 0x0c, 0x03, 0x00, 0x03, 0x80, 0x69, 0xf7, 0x83, 0x05, 0x82, 0x18,
	0xe8, 0x80, 0x7c, 0xf7, 0x82, 0x00, 0x0c, 0xf4, 0x00, 0x80, 0x84, 0xf7, 0x0e, 0x01, 0x3f, 0x3e,
	0x0b, 0x02, 0x0a, 0x02, 0x80, 0x90, 0xf7, 0x02, 0x80, 0x97, 0xf7, 0xfe, 0x80, 0x9b, 0xf7, 0x0e,
	0x01, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x80, 0x9f, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

TRDOS_DIR_ELEMENT sbootdir = { {'b','o','o','t',' ',' ',' ',' '}, 'B', 0xB4, 0xB4, (sizeof(sbootimage)+255)/256, 0, 0 };

long CalcCRC32(long CRC, unsigned char Symbol)
{
	long temp;
	CRC ^= -1l ^ Symbol;
	for (int k = 8; k--;)
	{
		temp = -(CRC & 1), CRC >>= 1, CRC ^= 0xEDB88320ul & temp;
	}
	CRC ^= -1l;
	return CRC;
}

long filelength(int hfile)
{
	long ret = lseek(hfile, 0, SEEK_END);
	lseek(hfile, 0, SEEK_SET);
	return ret;
}

//----------------------------------------------------------------------------
TDiskImage::TDiskImage()
{
	for (int t = 0; t < 256; t++)
		for (int s = 0; s < 256; s++)
		{
			FTrackLength[t][s] = 0;
			FTracksPtr[t][s][0] = NULL;
			FTracksPtr[t][s][1] = NULL;
		}

	DiskPresent = false;
	ReadOnly = true;
	Changed = false;
	FType = DIT_UNK;
	MaxTrack = 81;
	MaxSide = 0x01;
}
//-----------------------------------------------------------------------------
TDiskImage::~TDiskImage()
{
	ReadOnly = true;
	DiskPresent = false;
	Changed = false;
	FType = DIT_UNK;

	for (int t = 0; t < 256; t++)
		for (int s = 0; s < 256; s++)
		{
			FTrackLength[t][s] = 0;
			if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0];
			FTracksPtr[t][s][0] = NULL;
			if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1];
			FTracksPtr[t][s][1] = NULL;
		}
}
//-----------------------------------------------------------------------------
unsigned short TDiskImage::MakeVGCRC(unsigned char *data, unsigned long length)
{
	unsigned short CRC = 0xFFFF;
	for (unsigned int i = 0; i < length; i++)
	{
		CRC ^= data[i] << 8;
		for (unsigned int j = 0; j < 8; j++)
		{
			if (CRC & 0x8000) CRC = (CRC << 1) ^ 0x1021;
			else CRC <<= 1;
		}
	}
	return CRC;          // H<-->L !!!
}
//-----------------------------------------------------------------------------
void TDiskImage::ApplySectorCRC(VGFIND_SECTOR vgfs)
{
	unsigned char *TrackPtr = vgfs.vgfa.TrackPointer;
	unsigned int TrackLen = vgfs.vgfa.TrackLength;
	unsigned int len = vgfs.OffsetEndSector - vgfs.MarkedOffsetSector;
	if (vgfs.OffsetEndSector < vgfs.MarkedOffsetSector)
		len = (TrackLen - vgfs.MarkedOffsetSector) + vgfs.OffsetEndSector;

	unsigned int off1 = vgfs.MarkedOffsetSector;
	unsigned int len1 = TrackLen - vgfs.MarkedOffsetSector;
	if (len1 > len) len1 = len;
	unsigned int off2 = 0;
	unsigned int len2 = 0;
	if (len1 < len) len2 = len - len1;

	unsigned int i;
	unsigned short CRC = 0xFFFF;
	for (i = 0; i < len1; i++)
	{
		CRC ^= TrackPtr[off1 + i] << 8;
		for (unsigned int j = 0; j < 8; j++)
		{
			if (CRC & 0x8000) CRC = (CRC << 1) ^ 0x1021;
			else CRC <<= 1;
		}
	}
	for (i = 0; i < len2; i++)
	{
		CRC ^= TrackPtr[off2 + i] << 8;
		for (unsigned int j = 0; j < 8; j++)
		{
			if (CRC & 0x8000) CRC = (CRC << 1) ^ 0x1021;
			else CRC <<= 1;
		}
	}
	unsigned int crcoff = (off1 + len1) % TrackLen;
	if (len2) crcoff = (off2 + len2) % TrackLen;

	TrackPtr[crcoff] = (unsigned char)(CRC >> 8);
	TrackPtr[(crcoff + 1) % TrackLen] = (unsigned char)(CRC & 0xFF);
}
//-----------------------------------------------------------------------------
//
// DANGER!  CRC checking not prepared for track length overflow!
//
bool TDiskImage::FindADMark(unsigned char CYL, unsigned char SIDE,
	unsigned int FromOffset,
	VGFIND_ADM *vgfa)
{
	vgfa->TrackPointer = NULL;
	vgfa->ClkPointer = NULL;
	vgfa->TrackLength = 0;
	vgfa->ADMPointer = NULL;
	vgfa->ADMLength = 0;
	vgfa->FoundADM = false;
	vgfa->CRCOK = false;

	if ((!DiskPresent) |
		((CYL > MaxTrack) || (SIDE > MaxSide)) |
		((!FTracksPtr[CYL][SIDE][0]) || (!FTracksPtr[CYL][SIDE][1])))
	{
		return false;           // ERROR: disk not ready
	}

	unsigned char *track = vgfa->TrackPointer = FTracksPtr[CYL][SIDE][0];
	unsigned char *clks = vgfa->ClkPointer = FTracksPtr[CYL][SIDE][1];
	unsigned int tlen = vgfa->TrackLength = FTrackLength[CYL][SIDE];

	unsigned int off, rc;

	unsigned int pos = FromOffset;
	for (; pos < tlen + FromOffset; pos++)
	{
		off = pos%tlen;
		if ((track[off] == 0xA1) && (clks[off])) // fnd Mark
		{
			off = (off + 1) % tlen;

			rc = tlen;
			while ((track[off] == 0xA1) && (clks[off])) // repeat Mark
			{
				if (!rc) return false;           // ERROR: MFM marks all disk
				off = (off + 1) % tlen;
				rc--;
			}

			if (track[off] != 0xFE) continue;

			off = (off + 1) % tlen;

			vgfa->FoundADM = true;
			vgfa->MarkedOffsetADM = pos%tlen;
			vgfa->OffsetADM = off;
			vgfa->OffsetEndADM = (off + 6) % tlen;
			vgfa->ADMLength = 6;
			vgfa->ADMPointer = track + off;

			unsigned short crc = MakeVGCRC(track + (pos%tlen), (off - (pos%tlen)) + 4);

			vgfa->CRCOK = (track[(off + 4) % tlen] == (crc >> 8)) && (track[(off + 5) % tlen] == (crc & 0xFF));

			return true;
		}
	}

	return false;
}
//-----------------------------------------------------------------------------
//
// DANGER!  CRC checking not prepared for track length overflow!
//
bool TDiskImage::FindSector(unsigned char CYL, unsigned char SIDE,
	unsigned char SECT,
	VGFIND_SECTOR *vgfs, unsigned int FromOffset)
{
	vgfs->SectorPointer = NULL;
	vgfs->SectorLength = 0;
	vgfs->FoundDATA = false;
	vgfs->CRCOK = false;

	if ((!DiskPresent) |
		((CYL > MaxTrack) || (SIDE > MaxSide)) |
		((!FTracksPtr[CYL][SIDE][0]) || (!FTracksPtr[CYL][SIDE][1])))
	{
		vgfs->vgfa.TrackPointer = NULL;
		vgfs->vgfa.ClkPointer = NULL;
		vgfs->vgfa.TrackLength = 0;
		vgfs->vgfa.ADMPointer = NULL;
		vgfs->vgfa.ADMLength = 0;
		vgfs->vgfa.FoundADM = false;
		vgfs->vgfa.CRCOK = false;
		return false;           // ERROR: disk not ready
	}

	unsigned int TrackOffset = FromOffset;

	bool FirstFind = true;
	unsigned int FirstPos = 0;

	// Поиск адресной метки требуемого сектора...
	bool ADFOUND = false;
	for (;;)
	{
		if (!FindADMark(CYL, SIDE, TrackOffset, &(vgfs->vgfa)))
			return false;          // ERROR: No ADMARK found on track

		if (vgfs->vgfa.TrackPointer[(vgfs->vgfa.OffsetADM + 2) % vgfs->vgfa.TrackLength] == SECT)
		{
			ADFOUND = true;
			break;
		}

		if (!FirstFind)
		{
			if (vgfs->vgfa.OffsetEndADM == FirstPos) break;
		}
		else
		{
			FirstPos = vgfs->vgfa.OffsetEndADM;
			FirstFind = false;
		}

		TrackOffset = vgfs->vgfa.OffsetEndADM;
	};

	if (!ADFOUND) return false;

	// ADRMARK нужного найден, поиск массива данных...

	unsigned char *track = vgfs->vgfa.TrackPointer;
	unsigned char *clks = vgfs->vgfa.ClkPointer;
	unsigned int tlen = vgfs->vgfa.TrackLength;

	unsigned int pos = vgfs->vgfa.OffsetEndADM;

	unsigned int off, rc;

	for (; pos < tlen * 2; pos++)
	{
		off = pos%tlen;
		if ((track[off] == 0xA1) && (clks[off])) // fnd Mark
		{
			off = (off + 1) % tlen;

			rc = tlen;
			while ((track[off] == 0xA1) && (clks[off])) // repeat Mark
			{
				if (!rc) return false;       // ERROR: MFM marks all disk
				off = (off + 1) % tlen;
				rc--;
			}

			if ((track[off] < 0xF8) || (track[off] > 0xFB))
			{
				break;                      // ERROR: data array not found
			}
			vgfs->DataMarker = track[off];

			off = (off + 1) % tlen;

			vgfs->FoundDATA = true;

			unsigned char SL = vgfs->vgfa.TrackPointer[(vgfs->vgfa.OffsetADM + 3) % vgfs->vgfa.TrackLength];
			vgfs->SectorLength = 128;
			if (SL) vgfs->SectorLength <<= SL;
			vgfs->SectorPointer = track + off;

			vgfs->MarkedOffsetSector = pos%tlen;
			vgfs->OffsetSector = off;
			vgfs->OffsetEndSector = (off + vgfs->SectorLength) % tlen;

			unsigned short crc = MakeVGCRC(track + (pos%tlen), (off - (pos%tlen)) + vgfs->SectorLength);
			vgfs->CRCOK = (track[(off + vgfs->SectorLength) % tlen] == (crc >> 8)) && (track[(off + vgfs->SectorLength + 1) % tlen] == (crc & 0xFF));

			return true;                         // OK read
		}
	}

	return false;
}
//-----------------------------------------------------------------------------
bool TDiskImage::FindTrack(unsigned char CYL, unsigned char SIDE, VGFIND_TRACK *vgft)
{
	vgft->FoundTrack = false;
	vgft->TrackPointer = NULL;
	vgft->ClkPointer = NULL;
	vgft->TrackLength = 0;

	if ((!DiskPresent) |
		((CYL > MaxTrack) || (SIDE > MaxSide)) |
		((!FTracksPtr[CYL][SIDE][0]) || (!FTracksPtr[CYL][SIDE][1])))
	{
		return false;           // ERROR: disk not ready
	}

	vgft->TrackPointer = FTracksPtr[CYL][SIDE][0];
	vgft->ClkPointer = FTracksPtr[CYL][SIDE][1];
	vgft->TrackLength = FTrackLength[CYL][SIDE];
	vgft->FoundTrack = true;
	return true;
}

//-----------------------------------------------------------------------------
void TDiskImage::Open(const char *filename, bool ROnly)
{
	const char *ext = "";
	if (strlen(filename) > 4) ext = filename + strlen(filename) - 4;

	TDiskImageType typ = DIT_UNK;
	if (!strcasecmp(ext, ".SCL")) typ = DIT_SCL;
	if (!strcasecmp(ext, ".FDI")) typ = DIT_FDI;
	if (!strcasecmp(ext, ".UDI")) typ = DIT_UDI;
	if (!strcasecmp(ext, ".TD0")) typ = DIT_TD0;
	if (!strcasecmp(ext, ".FDD")) typ = DIT_FDD;
	if (!memcmp(ext + 1, ".$", 2)) typ = DIT_HOB;
	if (!memcmp(ext + 1, ".!", 2)) typ = DIT_HOB;

	if (!((FType == DIT_HOB) && (typ == DIT_HOB)))     // if not hobeta clear disk...
	{
		ReadOnly = true;
		DiskPresent = false;
		Changed = false;
		FType = DIT_UNK;

		for (int t = 0; t < 256; t++)
			for (int s = 0; s < 256; s++)
			{
				FTrackLength[t][s] = 0;
				if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0];
				FTracksPtr[t][s][0] = NULL;
				if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1];
				FTracksPtr[t][s][1] = NULL;
			}
	}

	if (typ == DIT_UNK)
	{
		ShowError(ERR_UNKFORMAT);
		return;
	}
	FType = typ;

	int hfile = open(filename, O_RDONLY | O_CLOEXEC);

	if (hfile < 0)
	{
		char sbuf[8192];
		sprintf(sbuf, ERR_OPEN" %s", filename);
		ShowError(sbuf);
		return;
	}

	if (typ == DIT_SCL) readSCL(hfile, ROnly);
	if (typ == DIT_FDI) readFDI(hfile, ROnly);
	if (typ == DIT_UDI) readUDI(hfile, ROnly);
	if (typ == DIT_TD0) readTD0(hfile, ROnly);
	if (typ == DIT_FDD) readFDD(hfile, ROnly);
	if (typ == DIT_HOB) readHOB(hfile);

	close(hfile);
}
//-----------------------------------------------------------------------------
void TDiskImage::formatTRDOS(unsigned int Tcount, unsigned int Scount)
{
	MaxTrack = Tcount - 1;
	MaxSide = Scount - 1;

	unsigned short TotalSecs = Tcount*Scount * 16 - 16;

	// форматирование нового диска под TR-DOS (16 x 256bytes sector per track)...
	unsigned int ptrcrc;
	unsigned int r;
	unsigned short vgcrc;
	for (unsigned int trk = 0; trk <= unsigned(MaxTrack); trk++)
		for (unsigned int side = 0; side <= unsigned(MaxSide); side++)
		{
			FTrackLength[trk][side] = 6250;

			FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // trk img
			FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // clk img

			unsigned int tptr = 0;
			for (int sec = 0; sec < 16; sec++)
			{
				for (r = 0; r < 10; r++)        // Первый пробел
				{
					FTracksPtr[trk][side][0][tptr] = 0x4E;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				for (r = 0; r < 12; r++)        // Синхропромежуток
				{
					FTracksPtr[trk][side][0][tptr] = 0x00;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				ptrcrc = tptr;
				for (r = 0; r < 3; r++)        // Синхроимпульс
				{
					FTracksPtr[trk][side][0][tptr] = 0xA1;
					FTracksPtr[trk][side][1][tptr++] = 0xFF;
				}
				FTracksPtr[trk][side][0][tptr] = 0xFE;   // Метка "Адрес"
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				FTracksPtr[trk][side][0][tptr] = (unsigned char)trk; // cyl
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = (unsigned char)0x00; // head (TR always 0)
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(sec + 1); // secN
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = (unsigned char)0x01; // len=256b
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc);
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF);
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				for (r = 0; r < 22; r++)        // Второй пробел
				{
					FTracksPtr[trk][side][0][tptr] = 0x4E;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				for (r = 0; r < 12; r++)        // Синхропромежуток
				{
					FTracksPtr[trk][side][0][tptr] = 0x00;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				ptrcrc = tptr;
				for (r = 0; r < 3; r++)        // Синхроимпульс
				{
					FTracksPtr[trk][side][0][tptr] = 0xA1;
					FTracksPtr[trk][side][1][tptr++] = 0xFF;
				}
				FTracksPtr[trk][side][0][tptr] = 0xFB;   // Метка "Данные"
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				for (r = 0; r < 256; r++)        // сектор 256байт
				{
					FTracksPtr[trk][side][0][tptr] = 0x00;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				if ((trk == 0) && (side == 0) && (sec == 8))      // make TR-DOS id
				{
					int ssec = tptr - 256;
					FTracksPtr[trk][side][0][ssec + 0xE1] = 0x00; // first free SECT
					FTracksPtr[trk][side][0][ssec + 0xE2] = 0x01; // first free TRACK
					FTracksPtr[trk][side][0][ssec + 0xE3] = 0x16; // 80trk DS
					FTracksPtr[trk][side][0][ssec + 0xE4] = 0x00; // file count
					*(unsigned short*)(FTracksPtr[trk][side][0] + ssec + 0xE5)
						= TotalSecs; // free SECS count
					FTracksPtr[trk][side][0][ssec + 0xE7] = 0x10; // TR-DOS id
					FTracksPtr[trk][side][0][ssec + 0xF4] = 0x00; // deleted file count

					memcpy(FTracksPtr[trk][side][0] + ssec + 0xF5,
						STR_CREATEDISKNAME"               ", 8); // disk name
					FTracksPtr[trk][side][0][ssec + 0xFD] = 0x00; // zero
					FTracksPtr[trk][side][0][ssec + 0xFE] = 0x00; // zero
					FTracksPtr[trk][side][0][ssec + 0xFF] = 0x00; // zero
				}

				vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc);
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF);
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				for (r = 0; r < 60; r++)        // Третий пробел
				{
					FTracksPtr[trk][side][0][tptr] = 0x4E;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
			}
			for (int eoftrk = tptr; eoftrk < 6250; eoftrk++)
			{
				FTracksPtr[trk][side][0][tptr] = 0x4E;
				FTracksPtr[trk][side][1][tptr++] = 0x00;
			}
		}
}
//-----------------------------------------------------------------------------
void TDiskImage::readUDI(int hfile, bool ronly)
{
	long fsize = filelength(hfile);
	if (fsize < 0)
	{
		ShowError(ERR_GETLEN);
		return;
	}

	unsigned char *ptr = (unsigned char*)new char[fsize + 1024 * 2048];
	if (!ptr)
	{
		ShowError(ERR_NOMEM);
		return;
	}

	unsigned long rsize = read(hfile, ptr, fsize + 1024);
	if (rsize < 16 + 4)
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}

	if (memcmp(ptr, "UDI!", 4) != 0)
	{
		delete ptr;
		ShowError(ERR_FORMAT" UDI!");
		return;
	}

	UDI_HEADER *udi_hdr = (UDI_HEADER*)(ptr);

	if ((udi_hdr->Version != 0x00) || (udi_hdr->_zero != 0x00) || (udi_hdr->ExtHdrLength != 0))
	{
		delete ptr;
		ShowError(ERR_FILEVER" UDI!");
		return;
	}
	if (rsize != (udi_hdr->UnpackedLength + 4))
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}

	MaxTrack = udi_hdr->MaxCylinder;
	MaxSide = udi_hdr->MaxSide;


	// checking for corrupt...
	unsigned int udiOFF = 0x10;

	unsigned int trk, side;

	for (trk = 0; trk <= unsigned(MaxTrack); trk++)
		for (side = 0; side <= unsigned(MaxSide); side++)
		{
			unsigned char frmt = ptr[udiOFF++];
			if (rsize < udiOFF + 4)
			{
				delete ptr;
				ShowError(ERR_CORRUPT);
				return;
			}

			if (frmt)
			{
				udiOFF += *((unsigned long*)(ptr + udiOFF));
				udiOFF += 4;
				continue;
			}

			unsigned ccctlen = *((unsigned short*)(ptr + udiOFF));
			udiOFF += ccctlen;
			udiOFF += 2;
			if (rsize < udiOFF + 4)
			{
				delete ptr;
				ShowError(ERR_CORRUPT);
				return;
			}

			udiOFF += ccctlen / 8 + ((ccctlen - (ccctlen / 8) * 8) ? 1 : 0);
			if (rsize < udiOFF + 4)
			{
				delete ptr;
				ShowError(ERR_CORRUPT);
				return;
			}
		}


	udiOFF = 0x10;

	unsigned int trklen;

	for (trk = 0; trk <= unsigned(MaxTrack); trk++)
		for (side = 0; side <= unsigned(MaxSide); side++)
		{
			if (udiOFF >= rsize) break;

			if (ptr[udiOFF++] != 0)        // non MFM track?
			{
				FTrackLength[trk][side] = 6250;
				// make unformatted track...
				FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // trk img
				FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // clk img
				for (unsigned ij = 0; ij < 6250; ij++)
				{
					FTracksPtr[trk][side][0][ij] = 0x00;
					FTracksPtr[trk][side][1][ij] = 0x00;
				}

				udiOFF += *((unsigned long*)(ptr + udiOFF));
				udiOFF += 4;
				continue;
			}
			trklen = *((unsigned short*)(ptr + udiOFF));
			udiOFF += 2;
			FTrackLength[trk][side] = trklen;

			// make unformatted track...
			FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // trk img
			FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // clk img
			for (unsigned ij = 0; ij < FTrackLength[trk][side]; ij++)
			{
				FTracksPtr[trk][side][0][ij] = 0x00;
				FTracksPtr[trk][side][1][ij] = 0x00;
			}

			memcpy(FTracksPtr[trk][side][0], ptr + udiOFF, FTrackLength[trk][side]);
			udiOFF += trklen;

			unsigned int MFMinfoLen = trklen / 8 + ((trklen - (trklen / 8) * 8) ? 1 : 0);

			unsigned char mask;
			for (unsigned i = 0; i < MFMinfoLen; i++)
			{
				mask = 0x01;
				for (int j = 0; j < 8; j++)
				{
					if (ptr[udiOFF] & mask) FTracksPtr[trk][side][1][i * 8 + j] = 0xFF;
					else FTracksPtr[trk][side][1][i * 8 + j] = 0x00;
					mask <<= 1;
				}
				udiOFF++;
			}
		}
	long CRC = -1l;
	for (unsigned int i = 0; i < udiOFF; i++) CRC = CalcCRC32(CRC, ptr[i]);


	if (udiOFF < rsize)
		if (*((long*)(ptr + udiOFF)) != CRC)
			ShowError(ERR_FILECRC" UDI!");

	delete ptr;
	ReadOnly = ronly;
	FType = DIT_UDI;
	DiskPresent = true;
}

//-----------------------------------------------------------------------------
void TDiskImage::writeTRD(fileTYPE *hfile)
{
	VGFIND_SECTOR vgfs;

	// prepare nullbuf...
	unsigned char nullbuf[256];
	for (int i = 0; i < 256; i++) nullbuf[i] = '*';
	memcpy(nullbuf, errsect, sizeof(errsect));

	for (unsigned int trk = 0; trk <= unsigned(MaxTrack); trk++)
		for (unsigned int side = 0; side <= unsigned(MaxSide); side++)
			for (unsigned int sec = 0; sec < 16; sec++)
			{
				if (FindSector(trk, side, sec + 1, &vgfs))
				{
					FileWriteAdv(hfile, vgfs.SectorPointer, 256);
					if ((!vgfs.CRCOK) || (!vgfs.vgfa.CRCOK)) printf("Warning: sector %d on track %d, side %d with BAD CRC!\n", sec + 1, trk, side);
					if (vgfs.SectorLength != 256) printf("Warning: sector %d on track %d, side %d is non 256 bytes!\n", sec + 1, trk, side);
				}
				else
				{
					FileWriteAdv(hfile, nullbuf, 256);
					printf("DANGER! Sector %d on track %d, side %d not found!\n", sec + 1, trk, side);
				}
			}
}

//-----------------------------------------------------------------------------
void TDiskImage::readFDI(int hfile, bool readonly)
{
	long fsize = filelength(hfile);
	if (fsize < 0)
	{
		ShowError(ERR_GETLEN);
		return;
	}

	unsigned char *ptr = (unsigned char*)new char[fsize + 1024 * 2048];
	if (!ptr)
	{
		ShowError(ERR_NOMEM);
		return;
	}

	unsigned long rsize = read(hfile, ptr, fsize);
	if (rsize < 14)
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}

	if (memcmp(ptr, "FDI", 3) != 0)
	{
		delete ptr;
		ShowError(ERR_FORMAT" FDI!");
		return;
	}

	// ==========================================
	// ********** Analyse FDI header ************...
	// ------------------------------------------
	unsigned short *fdihead = (unsigned short*)(ptr + 4);
	unsigned int fdiCylCount = fdihead[0];      // +4
	unsigned int fdiSideCount = fdihead[1];      // +6
												 //   unsigned int fdiOFFtext   = fdihead[2];      // +8
	unsigned int fdiOFFdata = fdihead[3];      // +A
	unsigned int fdiSIZEext = fdihead[4];      // +C

	if ((fdiCylCount > 256) || (fdiCylCount == 0))
	{
		delete ptr;
		ShowError(ERR_MANYCYLS);
		return;
	}
	if ((fdiSideCount > 256) || (fdiSideCount == 0))
	{
		delete ptr;
		ShowError(ERR_MANYSIDS);
		return;
	}

	MaxTrack = (unsigned char)(fdiCylCount - 1);
	MaxSide = (unsigned char)(fdiSideCount - 1);

	if (rsize < (0x0E + fdiSIZEext + (unsigned(MaxTrack) + 1)*(unsigned(MaxSide) + 1) * 7))
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}

	struct FDISECINFO
	{
		unsigned char ADAM[5];
		unsigned int SectorOffset;        // относит DataOffset
	};
	struct FDITRACKHDR
	{
		unsigned int DataOffset;          // относит начала файла
		unsigned int SectorCount;
		FDISECINFO SectorsInfo[256];
	};
	FDITRACKHDR *tracksinfo = new FDITRACKHDR[(unsigned(MaxTrack) + 1)*(unsigned(MaxSide) + 1)];

	unsigned int fdiOFF = 0x0E + fdiSIZEext;

	unsigned int trk, side;
	// Анализ области заголовков треков...
	for (trk = 0; trk <= unsigned(MaxTrack); trk++)
		for (side = 0; side <= unsigned(MaxSide); side++)
		{
			if (rsize < fdiOFF)
			{
				delete[] tracksinfo;
				delete ptr;
				ShowError(ERR_CORRUPT);
				return;
			}

			tracksinfo[trk*(MaxSide + 1) + side].DataOffset = *((unsigned long*)(ptr + fdiOFF));
			fdiOFF += 4;

			if (rsize < fdiOFFdata + tracksinfo[trk*(MaxSide + 1) + side].DataOffset)
			{
				delete[] tracksinfo;
				delete ptr;
				ShowError(ERR_CORRUPT);
				return;
			}

			fdiOFF += 2;      // "Всегда содержит 0 (резерв для модернизации)"

			tracksinfo[trk*(MaxSide + 1) + side].SectorCount = unsigned(ptr[fdiOFF++]);

			for (unsigned isec = 0; isec < tracksinfo[trk*(MaxSide + 1) + side].SectorCount; isec++)
			{
				memcpy(tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[isec].ADAM, ptr + fdiOFF, 5);
				fdiOFF += 5;
				tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[isec].SectorOffset = unsigned(*((unsigned short*)(ptr + fdiOFF)));
				fdiOFF += 2;

				if (rsize < fdiOFFdata + tracksinfo[trk*(MaxSide + 1) + side].DataOffset + tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[isec].SectorOffset)
				{
					delete[] tracksinfo;
					delete ptr;
					ShowError(ERR_CORRUPT);
					return;
				}
			}
		}

	// форматирование нового диска и размещение FDI секторов...
	unsigned int ptrcrc;
	unsigned int r;
	unsigned short vgcrc;
	unsigned int trkdatalen;
	unsigned SecCount;
	unsigned SL;

	for (trk = 0; trk <= unsigned(MaxTrack); trk++)
		for (side = 0; side <= unsigned(MaxSide); side++)
		{
			FTrackLength[trk][side] = 6250;

			// make unformatted track...
			FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // trk img
			FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // clk img
			for (unsigned ij = 0; ij < 6250; ij++)
			{
				FTracksPtr[trk][side][0][ij] = 0x00;
				FTracksPtr[trk][side][1][ij] = 0x00;
			}

			SecCount = tracksinfo[trk*(MaxSide + 1) + side].SectorCount;

			// Вычисляем необходимое число байт под данные:
			trkdatalen = 0;
			for (unsigned int ilsec = 0; ilsec < SecCount; ilsec++)
			{
				trkdatalen += 2 + 6;     // for marks:   0xA1, 0xFE, 6bytes
				SL = unsigned(tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[ilsec].ADAM[3]);
				if (!SL) SL = 128;
				else SL = 128 << SL;

				if (tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[ilsec].ADAM[4] & 0x40)
					SL = 0;          // заголовок без массива данных
				else
					trkdatalen += 4;       // for data header/crc: 0xA1, 0xFB, ...,2bytes

				trkdatalen += SL;
			}

			if (trkdatalen + SecCount*(3 + 2) > 6250)    // 3x4E & 2x00 per sec checking
			{
				delete[] tracksinfo;
				delete ptr;
				for (int t = 0; t < 256; t++)
					for (int s = 0; s < 256; s++)
					{
						FTrackLength[t][s] = 0;
						if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0];
						FTracksPtr[t][s][0] = NULL;
						if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1];
						FTracksPtr[t][s][1] = NULL;
					}
				ShowError(ERR_IMPOSSIBLE);
				return;
			}

			unsigned int FreeSpace = 6250 - (trkdatalen + SecCount*(3 + 2));

			unsigned int SynchroPulseLen = 1; // 1 уже учтен в trkdatalen...
			unsigned int FirstSpaceLen = 1;
			unsigned int SecondSpaceLen = 1;
			unsigned int ThirdSpaceLen = 1;
			unsigned int SynchroSpaceLen = 1;
			FreeSpace -= FirstSpaceLen + SecondSpaceLen + ThirdSpaceLen + SynchroSpaceLen;

			// Распределяем длины пробелов и синхропромежутка:
			while (FreeSpace > 0)
			{
				if (FreeSpace >= (SecCount * 2))
					if (SynchroSpaceLen < 12) { SynchroSpaceLen++; FreeSpace -= SecCount * 2; } // Synchro for ADM & DATA
				if (FreeSpace < SecCount) break;

				if (FirstSpaceLen < 10) { FirstSpaceLen++; FreeSpace -= SecCount; }
				if (FreeSpace < SecCount) break;
				if (SecondSpaceLen < 22) { SecondSpaceLen++; FreeSpace -= SecCount; }
				if (FreeSpace < SecCount) break;
				if (ThirdSpaceLen < 60) { ThirdSpaceLen++; FreeSpace -= SecCount; }
				if (FreeSpace < SecCount) break;

				if ((SynchroSpaceLen >= 12) && (FirstSpaceLen >= 10) && (SecondSpaceLen >= 22) && (ThirdSpaceLen >= 60)) break;
			};
			// по возможности делаем три синхроимпульса...
			if (FreeSpace >(SecCount * 2) + 10) { SynchroPulseLen++; FreeSpace -= SecCount; }
			if (FreeSpace >(SecCount * 2) + 9) SynchroPulseLen++;

			// Форматируем дорожку...

			unsigned int tptr = 0;
			for (unsigned sec = 0; sec < SecCount; sec++)
			{
				for (r = 0; r < FirstSpaceLen; r++)        // Первый пробел
				{
					FTracksPtr[trk][side][0][tptr] = 0x4E;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				for (r = 0; r < SynchroSpaceLen; r++)        // Синхропромежуток
				{
					FTracksPtr[trk][side][0][tptr] = 0x00;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				ptrcrc = tptr;
				for (r = 0; r < SynchroPulseLen; r++)        // Синхроимпульс
				{
					FTracksPtr[trk][side][0][tptr] = 0xA1;
					FTracksPtr[trk][side][1][tptr++] = 0xFF;
				}
				FTracksPtr[trk][side][0][tptr] = 0xFE;   // Метка "Адрес"
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				FTracksPtr[trk][side][0][tptr] = tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[0]; // cyl
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[1]; // head
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[2]; // secN
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[3]; // len code
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc);
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF);
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				for (r = 0; r < SecondSpaceLen; r++)        // Второй пробел
				{
					FTracksPtr[trk][side][0][tptr] = 0x4E;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				for (r = 0; r < SynchroSpaceLen; r++)        // Синхропромежуток
				{
					FTracksPtr[trk][side][0][tptr] = 0x00;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}

				unsigned char fdiSectorFlags = tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[4];

				// !!!!!!!!!
				// !WARNING! this feature of FDI format is NOT FULL DOCUMENTED!!!
				// !!!!!!!!!
				//
				//  Flags::bit6 - Возможно, 1 в данном разряде
				//                будет обозначать адресный маркер без области данных.
				//

				if (!(fdiSectorFlags & 0x40)) // oh-oh, data area not present... ;-)
				{
					ptrcrc = tptr;
					for (r = 0; r < SynchroPulseLen; r++)        // Синхроимпульс
					{
						FTracksPtr[trk][side][0][tptr] = 0xA1;
						FTracksPtr[trk][side][1][tptr++] = 0xFF;
					}

					if (fdiSectorFlags & 0x80)
						FTracksPtr[trk][side][0][tptr] = 0xF8;   // Метка "Удаленные данные"
					else
						FTracksPtr[trk][side][0][tptr] = 0xFB;   // Метка "Данные"
					FTracksPtr[trk][side][1][tptr++] = 0x00;


					SL = unsigned(tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[3]);
					if (!SL) SL = 128;
					else SL = 128 << SL;

					unsigned int secDATAOFF = fdiOFFdata + tracksinfo[trk*(MaxSide + 1) + side].DataOffset + tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].SectorOffset;

					for (r = 0; r < SL; r++)        // сектор SL байт
					{
						FTracksPtr[trk][side][0][tptr] = ptr[secDATAOFF + r];
						FTracksPtr[trk][side][1][tptr++] = 0x00;
					}

					vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc);


					if (fdiSectorFlags & 0x3F)        // CRC correct?
					{
						FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC
						FTracksPtr[trk][side][1][tptr++] = 0x00;
						FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF);
						FTracksPtr[trk][side][1][tptr++] = 0x00;
					}
					else     // oh-oh, high technology... CRC bad... ;-)
					{
						FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8) ^ 0xFF; // emulation bad CRC... ;)
						FTracksPtr[trk][side][1][tptr++] = 0x00;
						FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF) ^ 0xFF;  // --//-- ;)
						FTracksPtr[trk][side][1][tptr++] = 0x00;
					}
				}


				for (r = 0; r < ThirdSpaceLen; r++)        // Третий пробел
				{
					FTracksPtr[trk][side][0][tptr] = 0x4E;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
			}
			for (int eoftrk = tptr; eoftrk < 6250; eoftrk++)
			{
				FTracksPtr[trk][side][0][tptr] = 0x4E;
				FTracksPtr[trk][side][1][tptr++] = 0x00;
			}
		}

	delete[] tracksinfo;
	delete ptr;
	ReadOnly = readonly;
	FType = DIT_FDI;
	DiskPresent = true;
}

//-----------------------------------------------------------------------------
void TDiskImage::readFDD(int hfile, bool readonly)
{

	long fsize = filelength(hfile);
	if (fsize < 0)
	{
		ShowError(ERR_GETLEN);
		return;
	}

	unsigned char *ptr = (unsigned char*)new char[fsize + 1024 * 32];
	if (!ptr)
	{
		ShowError(ERR_NOMEM);
		return;
	}

	unsigned long rsize = read(hfile, ptr, fsize);
	if (rsize < sizeof(FDD_MAIN_HEADER))
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}

	FDD_MAIN_HEADER *fdd_hdr = (FDD_MAIN_HEADER*)ptr;

	int MaxC = fdd_hdr->MaxTracks;
	int MaxH = fdd_hdr->MaxHeads;

	if (MaxH > 2)
	{
		delete ptr;
		ShowError(ERR_MANYSIDS);
		return;
	}


	MaxH = (MaxH - 1) & 0xFF;
	MaxC = (MaxC - 1) & 0xFF;


	MaxTrack = MaxC;
	MaxSide = MaxH;


	// форматирование нового диска и размещение FDD секторов...
	unsigned int ptrcrc;
	unsigned int r;
	unsigned short vgcrc;
	unsigned int trkdatalen;
	unsigned SecCount;
	unsigned SL;

	FDD_TRACK_HEADER *trackinfo;

	unsigned int trk, side;

	for (trk = 0; trk <= unsigned(MaxTrack); trk++)
		for (side = 0; side <= unsigned(MaxSide); side++)
		{
			FTrackLength[trk][side] = 6250;

			// make unformatted track...
			FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // trk img
			FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // clk img
			for (unsigned ij = 0; ij < 6250; ij++)
			{
				FTracksPtr[trk][side][0][ij] = 0x00;
				FTracksPtr[trk][side][1][ij] = 0x00;
			}

			if ((fdd_hdr->DataOffset[trk*(MaxSide + 1) + side] + 2) > int(rsize))
			{
				delete ptr;
				for (int t = 0; t < 256; t++)
					for (int s = 0; s < 256; s++)
					{
						FTrackLength[t][s] = 0;
						if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0];
						FTracksPtr[t][s][0] = NULL;
						if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1];
						FTracksPtr[t][s][1] = NULL;
					}
				ShowError(ERR_CORRUPT);
				return;
			}

			trackinfo = (FDD_TRACK_HEADER *)(ptr + fdd_hdr->DataOffset[trk*(MaxSide + 1) + side]);

			SecCount = trackinfo->SectNum;

			if ((2 + SecCount * 8 + fdd_hdr->DataOffset[trk*(MaxSide + 1) + side]) > rsize)
			{
				delete ptr;
				for (int t = 0; t < 256; t++)
					for (int s = 0; s < 256; s++)
					{
						FTrackLength[t][s] = 0;
						if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0];
						FTracksPtr[t][s][0] = NULL;
						if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1];
						FTracksPtr[t][s][1] = NULL;
					}
				ShowError(ERR_CORRUPT);
				return;
			}
			else if (trackinfo->sect[SecCount - 1].SectPos > int(rsize))
			{
				delete ptr;
				for (int t = 0; t < 256; t++)
					for (int s = 0; s < 256; s++)
					{
						FTrackLength[t][s] = 0;
						if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0];
						FTracksPtr[t][s][0] = NULL;
						if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1];
						FTracksPtr[t][s][1] = NULL;
					}
				ShowError(ERR_CORRUPT);
				return;
			}



			// Вычисляем необходимое число байт под данные:
			trkdatalen = 0;
			for (unsigned int ilsec = 0; ilsec < SecCount; ilsec++)
			{
				trkdatalen += 2 + 6;     // for marks:   0xA1, 0xFE, 6bytes
				SL = unsigned(trackinfo->sect[ilsec].size);
				if (!SL) SL = 128;
				else SL = 128 << SL;

				trkdatalen += 4;       // for data header/crc: 0xA1, 0xFB, ...,2bytes

				trkdatalen += SL;
			}

			if (trkdatalen + SecCount*(3 + 2) > 6250)    // 3x4E & 2x00 per sec checking
			{
				delete ptr;
				for (int t = 0; t < 256; t++)
					for (int s = 0; s < 256; s++)
					{
						FTrackLength[t][s] = 0;
						if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0];
						FTracksPtr[t][s][0] = NULL;
						if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1];
						FTracksPtr[t][s][1] = NULL;
					}
				ShowError(ERR_IMPOSSIBLE);
				return;
			}

			unsigned int FreeSpace = 6250 - (trkdatalen + SecCount*(3 + 2));

			unsigned int SynchroPulseLen = 1; // 1 уже учтен в trkdatalen...
			unsigned int FirstSpaceLen = 1;
			unsigned int SecondSpaceLen = 1;
			unsigned int ThirdSpaceLen = 1;
			unsigned int SynchroSpaceLen = 1;
			FreeSpace -= FirstSpaceLen + SecondSpaceLen + ThirdSpaceLen + SynchroSpaceLen;

			// Распределяем длины пробелов и синхропромежутка:
			while (FreeSpace > 0)
			{
				if (FreeSpace >= (SecCount * 2))
					if (SynchroSpaceLen < 12) { SynchroSpaceLen++; FreeSpace -= SecCount * 2; } // Synchro for ADM & DATA
				if (FreeSpace < SecCount) break;

				if (FirstSpaceLen < 10) { FirstSpaceLen++; FreeSpace -= SecCount; }
				if (FreeSpace < SecCount) break;
				if (SecondSpaceLen < 22) { SecondSpaceLen++; FreeSpace -= SecCount; }
				if (FreeSpace < SecCount) break;
				if (ThirdSpaceLen < 60) { ThirdSpaceLen++; FreeSpace -= SecCount; }
				if (FreeSpace < SecCount) break;

				if ((SynchroSpaceLen >= 12) && (FirstSpaceLen >= 10) && (SecondSpaceLen >= 22) && (ThirdSpaceLen >= 60)) break;
			};
			// по возможности делаем три синхроимпульса...
			if (FreeSpace >(SecCount * 2) + 10) { SynchroPulseLen++; FreeSpace -= SecCount; }
			if (FreeSpace >(SecCount * 2) + 9) SynchroPulseLen++;

			// Форматируем дорожку...

			unsigned int tptr = 0;
			for (unsigned sec = 0; sec < SecCount; sec++)
			{
				for (r = 0; r < FirstSpaceLen; r++)        // Первый пробел
				{
					FTracksPtr[trk][side][0][tptr] = 0x4E;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				for (r = 0; r < SynchroSpaceLen; r++)        // Синхропромежуток
				{
					FTracksPtr[trk][side][0][tptr] = 0x00;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				ptrcrc = tptr;
				for (r = 0; r < SynchroPulseLen; r++)        // Синхроимпульс
				{
					FTracksPtr[trk][side][0][tptr] = 0xA1;
					FTracksPtr[trk][side][1][tptr++] = 0xFF;
				}
				FTracksPtr[trk][side][0][tptr] = 0xFE;   // Метка "Адрес"
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				FTracksPtr[trk][side][0][tptr] = trackinfo->sect[sec].trk;  // cyl
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = trackinfo->sect[sec].side; // head
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = trackinfo->sect[sec].sect; // secN
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = trackinfo->sect[sec].size; // len code
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc);
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF);
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				for (r = 0; r < SecondSpaceLen; r++)        // Второй пробел
				{
					FTracksPtr[trk][side][0][tptr] = 0x4E;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				for (r = 0; r < SynchroSpaceLen; r++)        // Синхропромежуток
				{
					FTracksPtr[trk][side][0][tptr] = 0x00;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}


				// DATA AM
				ptrcrc = tptr;
				for (r = 0; r < SynchroPulseLen; r++)        // Синхроимпульс
				{
					FTracksPtr[trk][side][0][tptr] = 0xA1;
					FTracksPtr[trk][side][1][tptr++] = 0xFF;
				}

				FTracksPtr[trk][side][0][tptr] = 0xFB;   // Метка "Данные"
				FTracksPtr[trk][side][1][tptr++] = 0x00;


				SL = unsigned(trackinfo->sect[sec].size);
				if (!SL) SL = 128;
				else SL = 128 << SL;

				unsigned int secDATAOFF = trackinfo->sect[sec].SectPos;

				for (r = 0; r < SL; r++)        // сектор SL байт
				{
					FTracksPtr[trk][side][0][tptr] = ptr[secDATAOFF + r];
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}

				vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc);


				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF);
				FTracksPtr[trk][side][1][tptr++] = 0x00;


				for (r = 0; r < ThirdSpaceLen; r++)        // Третий пробел
				{
					FTracksPtr[trk][side][0][tptr] = 0x4E;
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
			}
			for (int eoftrk = tptr; eoftrk < 6250; eoftrk++)
			{
				FTracksPtr[trk][side][0][tptr] = 0x4E;
				FTracksPtr[trk][side][1][tptr++] = 0x00;
			}
		}

	delete ptr;
	ReadOnly = readonly;
	FType = DIT_FDD;
	DiskPresent = true;

}

//-----------------------------------------------------------------------------
void TDiskImage::readSCL(int hfile, bool readonly)
{
	long fsize = filelength(hfile);
	if (fsize < 0)
	{
		ShowError(ERR_GETLEN);
		return;
	}
	unsigned char *ptr = (unsigned char*)new char[fsize + 1024 * 2048];
	if (!ptr)
	{
		ShowError(ERR_NOMEM);
		return;
	}
	unsigned long rsize = read(hfile, ptr, fsize);

	if (!rsize)
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}
	if (rsize < 9 + 4)      // header
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}
	if (memcmp(ptr, "SINCLAIR", 8) != 0)
	{
		delete ptr;
		ShowError(ERR_FORMAT" SCL!");
		return;
	}

	unsigned int FileCount = ptr[8];
	if (rsize < 9 + 4 + FileCount * 14)
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}

	TRDOS_DIR_ELEMENT *fileinfo[256];

	unsigned short FilesTotalSecs = 0;

	// checking for corrupt + SCL-CRC + FileDIRS parse
	unsigned long SCLCRC = 0;
	unsigned sclOFF = 0;
	unsigned int i, j;
	for (i = 0; i < 9; i++) SCLCRC += unsigned(ptr[sclOFF++]);

	for (i = 0; i < FileCount; i++)
	{
		fileinfo[i] = (TRDOS_DIR_ELEMENT*)(ptr + sclOFF);
		for (j = 0; j < 14; j++) SCLCRC += unsigned(ptr[sclOFF++]);
	}
	for (i = 0; i < FileCount; i++)
	{
		unsigned SL = unsigned(fileinfo[i]->SecLen) * 256;
		FilesTotalSecs += fileinfo[i]->SecLen;
		if (rsize < sclOFF + 4 + SL)
		{
			delete ptr;
			ShowError(ERR_CORRUPT);
			return;
		}
		for (j = 0; j < SL; j++) SCLCRC += unsigned(ptr[sclOFF++]);
	}

	if (*((unsigned long*)(ptr + sclOFF)) != SCLCRC)
		ShowError(ERR_FILECRC" SCL!");


	if (FilesTotalSecs < 2544) FilesTotalSecs = 2544;
	else
	{
		int cyls = ((16 + FilesTotalSecs) / (16 * 2)) + (((16 + FilesTotalSecs) % (16 * 2)) ? 1 : 0);
		FilesTotalSecs = (cyls * 16 * 2) - 16;
	}

	formatTRDOS((FilesTotalSecs + 16) / (16 * 2), 2);
	ReadOnly = true;
	FType = DIT_SCL;
	DiskPresent = true;

	sclOFF = 9 + 14 * FileCount;

	bool BOOTADD = true;
	unsigned char _FileCount = 0;
	unsigned char _DelFileCount = 0;

	for (i = 0; i < FileCount; i++)
	{
		if (fileinfo[i]->FileName[0] == 0x01) _DelFileCount++;
		_FileCount++;

		if (!strncasecmp(fileinfo[i]->FileName, "BOOT    B", 9))
		{
			BOOTADD = false;
		}
	}

	unsigned char SEC = 0, TRK = 1;
	unsigned short FreeSEC = 2544;
	unsigned int cnt = 0;
	unsigned int dirsec;

	TRDOS_DIR_ELEMENT trdosde;
	VGFIND_SECTOR vgfs;

	if (BOOTADD && (unsigned(_FileCount) + unsigned(_DelFileCount) < 127))
	{
		dirsec = ((cnt * 16) / 256) + 1;

		memcpy(&trdosde, &sbootdir, sizeof(sbootdir));

		trdosde.FirstSec = SEC;
		trdosde.FirstTrk = TRK;

		if (FindSector(0, 0, dirsec, &vgfs))         // DIR ELEMENT write
		{
			memcpy(vgfs.SectorPointer + ((cnt * 16) % 256), &trdosde, sizeof(trdosde));
			ApplySectorCRC(vgfs);
		}
		_FileCount++;
		cnt++;
		int _bOFF = 0;

		for (j = 0; j < unsigned(trdosde.SecLen); j++)
		{
			if (FindSector(TRK / 2, TRK % 2, SEC + 1, &vgfs))       // SECTOR write
			{
				memcpy(vgfs.SectorPointer, sbootimage + _bOFF, 256);
				ApplySectorCRC(vgfs);
			}
			_bOFF += 256;
			SEC++;
			FreeSEC--;
			if (SEC > 15) { SEC = 0; TRK++; }
		}
	}

	for (i = 0; i < FileCount; i++)
	{
		if (TRK >= (MaxTrack + 1)*(MaxSide + 1)) break;      // disk full ?

		memcpy(&trdosde, fileinfo[i], 14);

		trdosde.FirstSec = SEC;
		trdosde.FirstTrk = TRK;

		unsigned int dirsec = ((cnt * 16) / 256) + 1;
		if (FindSector(0, 0, dirsec, &vgfs))         // DIR ELEMENT write
		{
			memcpy(vgfs.SectorPointer + ((cnt * 16) % 256), &trdosde, 16);
			ApplySectorCRC(vgfs);
		}

		cnt++;

		for (j = 0; j < unsigned(trdosde.SecLen); j++)
		{
			if (FindSector(TRK / 2, TRK % 2, SEC + 1, &vgfs))       // SECTOR write
			{
				memcpy(vgfs.SectorPointer, ptr + sclOFF, 256);
				ApplySectorCRC(vgfs);
			}
			sclOFF += 256;
			SEC++;
			FreeSEC--;
			if (SEC > 15) { SEC = 0; TRK++; }

			if (TRK >= (MaxTrack + 1)*(MaxSide + 1)) break;      // disk full ?
		}
	}

	if (FindSector(0, 0, 9, &vgfs))         // update disk info
	{
		vgfs.SectorPointer[0xE1] = SEC;
		vgfs.SectorPointer[0xE2] = TRK;
		vgfs.SectorPointer[0xE4] = _FileCount;
		vgfs.SectorPointer[0xF4] = _DelFileCount;
		*((unsigned short*)(vgfs.SectorPointer + 0xE5)) = FreeSEC;
		ApplySectorCRC(vgfs);
	}

	delete ptr;
	ReadOnly = readonly;
}
//-----------------------------------------------------------------------------
void TDiskImage::readHOB(int hfile)
{
	long fsize = filelength(hfile);
	if (fsize < 0)
	{
		ShowError(ERR_GETLEN);
		return;
	}
	unsigned char *ptr = (unsigned char*)new char[fsize + 1024 * 2048];
	if (!ptr)
	{
		ShowError(ERR_NOMEM);
		return;
	}
	unsigned long rsize = read(hfile, ptr, fsize);

	if (!rsize)
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}
	if (rsize < 17)      // header
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}

	TRDOS_DIR_ELEMENT dired;
	memcpy(&dired, ptr, 14);

	unsigned short hobRealCRC = *((unsigned short*)(ptr + 0x0F));
	unsigned int DataLength = *((unsigned short*)(ptr + 0x0D));

	if (rsize < 17 + (DataLength & 0xFF00))
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}

	unsigned int i;
	unsigned short CRC = 0;
	for (i = 0; i < 15; i++) CRC = CRC + ptr[i];
	CRC *= 257;
	CRC += 105;          // сумма чисел от 0 до 14

	if (CRC != hobRealCRC)
		ShowError(ERR_FILECRC" HOBETA!");




	ReadOnly = true;
	if (!DiskPresent)
	{
		formatTRDOS(80, 2);
		FType = DIT_HOB;
		DiskPresent = true;
	}

	// --- read file...
	dired.SecLen = ptr[0x0E];            // число секторов файла

	VGFIND_SECTOR vgfs9;
	if (!FindSector(0, 0, 9, &vgfs9)) { delete ptr; return; }

	dired.FirstSec = vgfs9.SectorPointer[0xE1];
	dired.FirstTrk = vgfs9.SectorPointer[0xE2];

	VGFIND_SECTOR vgfs;

	unsigned char SEC = dired.FirstSec, TRK = dired.FirstTrk;
	unsigned short FreeSEC = *((unsigned short*)(vgfs9.SectorPointer + 0xE5));
	unsigned char FileCount = vgfs9.SectorPointer[0xE4];
	unsigned char DelFileCount = vgfs9.SectorPointer[0xF4];

	if (TRK >= 160)       // disk full ?
	{
		delete ptr;
		return;
	}

	for (unsigned int j = 0; j < unsigned(dired.SecLen); j++)
	{
		if (FindSector(TRK / 2, TRK % 2, SEC + 1, &vgfs))
		{
			memcpy(vgfs.SectorPointer, ptr + 17 + j * 256, 256);
			ApplySectorCRC(vgfs);
		}
		SEC++;
		FreeSEC--;
		if (SEC > 15) { SEC = 0; TRK++; }

		if (TRK >= 160) break;     // disk full?
	}

	if (FindSector(0, 0, ((FileCount * 16) / 256) + 1, &vgfs))
	{
		memcpy(vgfs.SectorPointer + ((FileCount * 16) % 256), &dired, 16);
		ApplySectorCRC(vgfs);
	}

	if (dired.FileName[0] == 0x01) DelFileCount++;
	FileCount++;

	vgfs9.SectorPointer[0xE1] = SEC;
	vgfs9.SectorPointer[0xE2] = TRK;
	*((unsigned short*)(vgfs9.SectorPointer + 0xE5)) = FreeSEC;
	vgfs9.SectorPointer[0xE4] = FileCount;
	vgfs9.SectorPointer[0xF4] = DelFileCount;
	ApplySectorCRC(vgfs9);
}
//-----------------------------------------------------------------------------
bool unpack_td0(unsigned char *data, long &size);
unsigned short TD0CRC(unsigned char *buf, unsigned int len);

#define WORD2(a,b) ((a)+(b)*0x100)

void TDiskImage::readTD0(int hfile, bool readonly)
{
	long fsize = filelength(hfile);
	if (fsize < 0)
	{
		ShowError(ERR_GETLEN);
		return;
	}
	unsigned char *ptr = (unsigned char*)new char[fsize + 256 * 20000];
	if (!ptr)
	{
		ShowError(ERR_NOMEM);
		return;
	}
	long rsize = read(hfile, ptr, fsize);

	TD0_MAIN_HEADER *td0hdr = (TD0_MAIN_HEADER*)ptr;
	TD0_INFO_DATA *td0inf = (TD0_INFO_DATA*)(ptr + 12);

	if (!rsize)
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}
	if (rsize < 12)      // header
	{
		delete ptr;
		ShowError(ERR_CORRUPT);
		return;
	}

	if ((*(short*)ptr != WORD2('T', 'D')) && (*(short*)ptr != WORD2('t', 'd')))// non TD0
	{
		delete ptr;
		ShowError(ERR_FORMAT" TD0!");
		return;
	}
	if (TD0CRC(ptr, 10) != td0hdr->CRC) // CRC bad...
	{
		delete ptr;
		ShowError(ERR_FILECRC" TD0!");
		return;
	}
	if ((td0hdr->Ver > 21) || (td0hdr->Ver < 10))           // 1.0 <= version <= 2.1...
	{
		delete ptr;
		ShowError(ERR_FILEVER" TD0!");
		return;
	}
	if (td0hdr->DataDOS != 0)           // if DOS allocated sectors only...
	{
		delete ptr;
		ShowError(ERR_TD0DOSALLOC);
		return;
	}
	if (!unpack_td0(ptr, rsize))
	{
		delete ptr;
		ShowError(ERR_FORMAT" TD0!");
		return;
	}

	// loading unpacked TD0...

	int tdOFF = 12;
	if (ptr[7] & 0x80) tdOFF += sizeof(TD0_INFO_DATA) + td0inf->strLen;

	TD0_TRACK_HEADER *tdtrk;
	TD0_SECT_HEADER *tdsect;

	MaxTrack = 0;
	MaxSide = 0;

	for (; tdOFF < rsize;)
	{
		tdtrk = (TD0_TRACK_HEADER*)(ptr + tdOFF);
		tdOFF += sizeof(TD0_TRACK_HEADER);

		if (tdOFF >= rsize) break;
		if (tdtrk->SectorCount == 0xFF) break;   // EOF marker


		unsigned trk = tdtrk->Track;
		unsigned side = tdtrk->Side;
		FTrackLength[trk][side] = 6250;

		// make unformatted track...
		FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // trk img
		FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024];      // clk img
		for (unsigned ij = 0; ij < 6250; ij++)
		{
			FTracksPtr[trk][side][0][ij] = 0x00;
			FTracksPtr[trk][side][1][ij] = 0x00;
		}


		unsigned SecCount = tdtrk->SectorCount;

		unsigned int tmpOFF = tdOFF;

		// Вычисляем необходимое число байт под данные:
		unsigned int trkdatalen = 0;
		unsigned int SL;
		for (unsigned int ilsec = 0; ilsec < SecCount; ilsec++)
		{
			tdsect = (TD0_SECT_HEADER*)(ptr + tmpOFF);
			tmpOFF += sizeof(TD0_SECT_HEADER) + tdsect->DataLength;

			trkdatalen += 2 + 6;     // for marks:   0xA1, 0xFE, 6bytes
			trkdatalen += 4;       // for data header/crc: 0xA1, 0xFB, ...,2bytes
								   //         SL = unsigned(tdsect->ADRM[3]);
								   //         if(!SL) SL = 128;
								   //         else SL = 128 << SL;
			SL = tdsect->DataLength - 1;
			trkdatalen += SL;
		}

		// проверка на возможность формата...
		if (trkdatalen + SecCount*(3 + 2) > 6250)    // 3x4E & 2x00 per sec checking
		{
			delete ptr;
			for (int t = 0; t < 256; t++)
				for (int s = 0; s < 256; s++)
				{
					FTrackLength[t][s] = 0;
					if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0];
					FTracksPtr[t][s][0] = NULL;
					if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1];
					FTracksPtr[t][s][1] = NULL;
				}
			ShowError(ERR_IMPOSSIBLE);
			return;
		}

		unsigned int FreeSpace = 6250 - (trkdatalen + SecCount*(3 + 2));

		unsigned int SynchroPulseLen = 1; // 1 уже учтен в trkdatalen...
		unsigned int FirstSpaceLen = 1;
		unsigned int SecondSpaceLen = 1;
		unsigned int ThirdSpaceLen = 1;
		unsigned int SynchroSpaceLen = 1;
		FreeSpace -= FirstSpaceLen + SecondSpaceLen + ThirdSpaceLen + SynchroSpaceLen;

		// Распределяем длины пробелов и синхропромежутка:
		while (FreeSpace > 0)
		{
			if (FreeSpace >= (SecCount * 2))
				if (SynchroSpaceLen < 12) { SynchroSpaceLen++; FreeSpace -= SecCount * 2; } // Synchro for ADM & DATA
			if (FreeSpace < SecCount) break;

			if (FirstSpaceLen < 10) { FirstSpaceLen++; FreeSpace -= SecCount; }
			if (FreeSpace < SecCount) break;
			if (SecondSpaceLen < 22) { SecondSpaceLen++; FreeSpace -= SecCount; }
			if (FreeSpace < SecCount) break;
			if (ThirdSpaceLen < 60) { ThirdSpaceLen++; FreeSpace -= SecCount; }
			if (FreeSpace < SecCount) break;

			if ((SynchroSpaceLen >= 12) && (FirstSpaceLen >= 10) && (SecondSpaceLen >= 22) && (ThirdSpaceLen >= 60)) break;
		};
		// по возможности делаем три синхроимпульса...
		if (FreeSpace >(SecCount * 2) + 10) { SynchroPulseLen++; FreeSpace -= SecCount; }
		if (FreeSpace >(SecCount * 2) + 9) SynchroPulseLen++;

		// Форматируем дорожку...

		unsigned int tptr = 0;
		unsigned int ptrcrc;
		unsigned int r;
		unsigned short vgcrc;
		for (unsigned sec = 0; sec < SecCount; sec++)
		{
			tdsect = (TD0_SECT_HEADER*)(ptr + tdOFF);
			tdOFF += sizeof(TD0_SECT_HEADER) + 1;

			for (r = 0; r < FirstSpaceLen; r++)        // Первый пробел
			{
				FTracksPtr[trk][side][0][tptr] = 0x4E;
				FTracksPtr[trk][side][1][tptr++] = 0x00;
			}
			for (r = 0; r < SynchroSpaceLen; r++)        // Синхропромежуток
			{
				FTracksPtr[trk][side][0][tptr] = 0x00;
				FTracksPtr[trk][side][1][tptr++] = 0x00;
			}
			ptrcrc = tptr;
			for (r = 0; r < SynchroPulseLen; r++)        // Синхроимпульс
			{
				FTracksPtr[trk][side][0][tptr] = 0xA1;
				FTracksPtr[trk][side][1][tptr++] = 0xFF;
			}
			FTracksPtr[trk][side][0][tptr] = 0xFE;   // Метка "Адрес"
			FTracksPtr[trk][side][1][tptr++] = 0x00;

			FTracksPtr[trk][side][0][tptr] = tdsect->ADRM[0]; // cyl
			FTracksPtr[trk][side][1][tptr++] = 0x00;
			FTracksPtr[trk][side][0][tptr] = tdsect->ADRM[1]; // head
			FTracksPtr[trk][side][1][tptr++] = 0x00;
			FTracksPtr[trk][side][0][tptr] = tdsect->ADRM[2]; // secN
			FTracksPtr[trk][side][1][tptr++] = 0x00;
			FTracksPtr[trk][side][0][tptr] = tdsect->ADRM[3]; // len code
			FTracksPtr[trk][side][1][tptr++] = 0x00;

			vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc);
			FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC
			FTracksPtr[trk][side][1][tptr++] = 0x00;
			FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF);
			FTracksPtr[trk][side][1][tptr++] = 0x00;

			for (r = 0; r < SecondSpaceLen; r++)        // Второй пробел
			{
				FTracksPtr[trk][side][0][tptr] = 0x4E;
				FTracksPtr[trk][side][1][tptr++] = 0x00;
			}
			for (r = 0; r < SynchroSpaceLen; r++)        // Синхропромежуток
			{
				FTracksPtr[trk][side][0][tptr] = 0x00;
				FTracksPtr[trk][side][1][tptr++] = 0x00;
			}

			if (tdsect->DataLength - 1) // oh-oh, data area not present... ;-)
			{
				ptrcrc = tptr;
				for (r = 0; r < SynchroPulseLen; r++)        // Синхроимпульс
				{
					FTracksPtr[trk][side][0][tptr] = 0xA1;
					FTracksPtr[trk][side][1][tptr++] = 0xFF;
				}

				FTracksPtr[trk][side][0][tptr] = 0xFB;   // Метка "Данные"
				FTracksPtr[trk][side][1][tptr++] = 0x00;

				//            SL = unsigned(tdsect->ADRM[3]);
				//            if(!SL) SL = 128;
				//            else SL = 128 << SL;
				SL = tdsect->DataLength - 1;

				for (r = 0; r < SL; r++)        // сектор SL байт
				{
					FTracksPtr[trk][side][0][tptr] = ptr[tdOFF + r];
					FTracksPtr[trk][side][1][tptr++] = 0x00;
				}
				tdOFF += SL;

				vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc);


				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC
				FTracksPtr[trk][side][1][tptr++] = 0x00;
				FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF);
				FTracksPtr[trk][side][1][tptr++] = 0x00;
			}

			for (r = 0; r < ThirdSpaceLen; r++)        // Третий пробел
			{
				FTracksPtr[trk][side][0][tptr] = 0x4E;
				FTracksPtr[trk][side][1][tptr++] = 0x00;
			}
		}
		for (int eoftrk = tptr; eoftrk < 6250; eoftrk++)
		{
			FTracksPtr[trk][side][0][tptr] = 0x4E;
			FTracksPtr[trk][side][1][tptr++] = 0x00;
		}

		if (unsigned(MaxTrack) < trk) MaxTrack = trk;
		if (unsigned(MaxSide) < side) MaxSide = side;
	}

	delete ptr;
	ReadOnly = readonly;
	FType = DIT_TD0;
	DiskPresent = true;
}

//-----------------------------------------------------------------------------
void TDiskImage::ShowError(const char *str)
{
	printf("DiskImage Error: %s\n", str);
}

//-----------------------------------------------------------------------------
// convert packed td0 to unpacked
unsigned short TD0CRC(unsigned char *buf, unsigned int len);
unsigned unpack_lzh(unsigned char *src, unsigned size, unsigned char *buf);
unsigned char *td0_dst, *td0_src;

void td0_move(unsigned size)
{
	memcpy(td0_dst, td0_src, size);
	td0_dst += size;
	td0_src += size;
}

//----------------------------------------------------------------------------
bool unpack_td0(unsigned char *data, long &size)
{
	if (size < 12) return false;
	if ((*(short*)data != WORD2('T', 'D')) && (*(short*)data != WORD2('t', 'd')))
		return false;             // non TD0
	if (TD0CRC(data, 10) != *((unsigned short*)(data + 0x0A)))
		return false;             // CRC bad...
	if (data[4] > 21)
		return false;             // version > 2.1...

	unsigned char *snbuf = (unsigned char*)new char[size * 2 + 1500000];  // if compressed then UUUUFF ;-/
	if (!snbuf) return false;

	memcpy(snbuf, data, size);
	if (*(short*)snbuf == WORD2('t', 'd')) // packed disk
	{
		if (snbuf[4] < 20)    // unsupported Old Advanced compression
		{
			delete snbuf;
			return false;
		}
		unpack_lzh((unsigned char*)data + 12, size - 12, (unsigned char*)snbuf + 12), *(short*)snbuf = WORD2('T', 'D');
	}

	td0_src = snbuf, td0_dst = data;
	td0_move(12);

	if (snbuf[7] & 0x80)  // additional info...
	{
		unsigned short *cs = (unsigned short*)(snbuf + 12 + 2);

		if (TD0CRC(snbuf + 12 + 2, 8 + *cs) != cs[-1])
		{
			delete snbuf;
			return false;
		}
		td0_move(10);
		td0_move(*((unsigned short*)(snbuf + 12 + 2)));
	}

	for (;;)
	{
		unsigned char s = *td0_src;
		td0_move(4);
		if (s == 0xFF) break;
		for (; s; s--)
		{
			//         unsigned char *sec = td0_src;
			unsigned size = 128; if (td0_src[3]) size <<= td0_src[3];
			td0_move(6);
			*(unsigned short*)td0_dst = size + 1; td0_dst += 2;
			*td0_dst++ = 0;
			unsigned char *dst = td0_dst;
			unsigned src_size = *(unsigned short*)td0_src; td0_src += 2;
			unsigned char *end_packed_data = td0_src + src_size;
			memset(td0_dst, 0, size);
			switch (*td0_src++)
			{
			case 0:
				memcpy(dst, td0_src, src_size - 1); break;
			case 1:
			{
				unsigned n = *(unsigned short*)td0_src;
				td0_src += 2;
				unsigned short data = *(unsigned short*)td0_src;
				for (; n; n--) *(unsigned short*)dst = data, dst += 2;
				break;
			}
			case 2:
			{
				unsigned short data;
				unsigned char s;
				do
				{
					switch (*td0_src++)
					{
					case 0:
						for (s = *td0_src++; s; s--) *dst++ = *td0_src++;
						break;
					case 1:
						s = *td0_src++;
						data = *(unsigned short*)td0_src;
						td0_src += 2;
						for (; s; s--) *(unsigned short*)dst = data, dst += 2;
						break;
					default: shit:
						delete snbuf;
						return false;  // "bad TD0 file"
					}
				} while (td0_src < end_packed_data);
				break;
			}
			default: goto shit;
			}
			td0_dst += size;
			td0_src = end_packed_data;
		}
	}
	size = unsigned(td0_dst) - unsigned(data);
	delete snbuf;
	return true;
}
//----------------------------------------------------------------------------
//
// TD0 CRC - table&proc grabed from TDCHECK.EXE by Alex Makeev
//
unsigned char tbltd0crc[512] = {
	0x00,0x00,0xA0,0x97,0xE1,0xB9,0x41,0x2E,0x63,0xE5,0xC3,0x72,0x82,0x5C,0x22,0xCB,
	0xC7,0xCA,0x67,0x5D,0x26,0x73,0x86,0xE4,0xA4,0x2F,0x04,0xB8,0x45,0x96,0xE5,0x01,
	0x2F,0x03,0x8F,0x94,0xCE,0xBA,0x6E,0x2D,0x4C,0xE6,0xEC,0x71,0xAD,0x5F,0x0D,0xC8,
	0xE8,0xC9,0x48,0x5E,0x09,0x70,0xA9,0xE7,0x8B,0x2C,0x2B,0xBB,0x6A,0x95,0xCA,0x02,
	0x5E,0x06,0xFE,0x91,0xBF,0xBF,0x1F,0x28,0x3D,0xE3,0x9D,0x74,0xDC,0x5A,0x7C,0xCD,
	0x99,0xCC,0x39,0x5B,0x78,0x75,0xD8,0xE2,0xFA,0x29,0x5A,0xBE,0x1B,0x90,0xBB,0x07,
	0x71,0x05,0xD1,0x92,0x90,0xBC,0x30,0x2B,0x12,0xE0,0xB2,0x77,0xF3,0x59,0x53,0xCE,
	0xB6,0xCF,0x16,0x58,0x57,0x76,0xF7,0xE1,0xD5,0x2A,0x75,0xBD,0x34,0x93,0x94,0x04,
	0xBC,0x0C,0x1C,0x9B,0x5D,0xB5,0xFD,0x22,0xDF,0xE9,0x7F,0x7E,0x3E,0x50,0x9E,0xC7,
	0x7B,0xC6,0xDB,0x51,0x9A,0x7F,0x3A,0xE8,0x18,0x23,0xB8,0xB4,0xF9,0x9A,0x59,0x0D,
	0x93,0x0F,0x33,0x98,0x72,0xB6,0xD2,0x21,0xF0,0xEA,0x50,0x7D,0x11,0x53,0xB1,0xC4,
	0x54,0xC5,0xF4,0x52,0xB5,0x7C,0x15,0xEB,0x37,0x20,0x97,0xB7,0xD6,0x99,0x76,0x0E,
	0xE2,0x0A,0x42,0x9D,0x03,0xB3,0xA3,0x24,0x81,0xEF,0x21,0x78,0x60,0x56,0xC0,0xC1,
	0x25,0xC0,0x85,0x57,0xC4,0x79,0x64,0xEE,0x46,0x25,0xE6,0xB2,0xA7,0x9C,0x07,0x0B,
	0xCD,0x09,0x6D,0x9E,0x2C,0xB0,0x8C,0x27,0xAE,0xEC,0x0E,0x7B,0x4F,0x55,0xEF,0xC2,
	0x0A,0xC3,0xAA,0x54,0xEB,0x7A,0x4B,0xED,0x69,0x26,0xC9,0xB1,0x88,0x9F,0x28,0x08,
	0xD8,0x8F,0x78,0x18,0x39,0x36,0x99,0xA1,0xBB,0x6A,0x1B,0xFD,0x5A,0xD3,0xFA,0x44,
	0x1F,0x45,0xBF,0xD2,0xFE,0xFC,0x5E,0x6B,0x7C,0xA0,0xDC,0x37,0x9D,0x19,0x3D,0x8E,
	0xF7,0x8C,0x57,0x1B,0x16,0x35,0xB6,0xA2,0x94,0x69,0x34,0xFE,0x75,0xD0,0xD5,0x47,
	0x30,0x46,0x90,0xD1,0xD1,0xFF,0x71,0x68,0x53,0xA3,0xF3,0x34,0xB2,0x1A,0x12,0x8D,
	0x86,0x89,0x26,0x1E,0x67,0x30,0xC7,0xA7,0xE5,0x6C,0x45,0xFB,0x04,0xD5,0xA4,0x42,
	0x41,0x43,0xE1,0xD4,0xA0,0xFA,0x00,0x6D,0x22,0xA6,0x82,0x31,0xC3,0x1F,0x63,0x88,
	0xA9,0x8A,0x09,0x1D,0x48,0x33,0xE8,0xA4,0xCA,0x6F,0x6A,0xF8,0x2B,0xD6,0x8B,0x41,
	0x6E,0x40,0xCE,0xD7,0x8F,0xF9,0x2F,0x6E,0x0D,0xA5,0xAD,0x32,0xEC,0x1C,0x4C,0x8B,
	0x64,0x83,0xC4,0x14,0x85,0x3A,0x25,0xAD,0x07,0x66,0xA7,0xF1,0xE6,0xDF,0x46,0x48,
	0xA3,0x49,0x03,0xDE,0x42,0xF0,0xE2,0x67,0xC0,0xAC,0x60,0x3B,0x21,0x15,0x81,0x82,
	0x4B,0x80,0xEB,0x17,0xAA,0x39,0x0A,0xAE,0x28,0x65,0x88,0xF2,0xC9,0xDC,0x69,0x4B,
	0x8C,0x4A,0x2C,0xDD,0x6D,0xF3,0xCD,0x64,0xEF,0xAF,0x4F,0x38,0x0E,0x16,0xAE,0x81,
	0x3A,0x85,0x9A,0x12,0xDB,0x3C,0x7B,0xAB,0x59,0x60,0xF9,0xF7,0xB8,0xD9,0x18,0x4E,
	0xFD,0x4F,0x5D,0xD8,0x1C,0xF6,0xBC,0x61,0x9E,0xAA,0x3E,0x3D,0x7F,0x13,0xDF,0x84,
	0x15,0x86,0xB5,0x11,0xF4,0x3F,0x54,0xA8,0x76,0x63,0xD6,0xF4,0x97,0xDA,0x37,0x4D,
	0xD2,0x4C,0x72,0xDB,0x33,0xF5,0x93,0x62,0xB1,0xA9,0x11,0x3E,0x50,0x10,0xF0,0x87,
};
unsigned short TD0CRC(unsigned char *buf, unsigned int len)
{
	unsigned short CRC = 0;
	int j;
	for (unsigned int i = 0; i < len; i++)
	{
		CRC ^= *buf++;
		j = CRC & 0xFF;
		CRC &= 0xFF00;
		CRC = (CRC << 8) | (CRC >> 8);
		CRC ^= ((unsigned short*)tbltd0crc)[j];
	}
	return (CRC << 8) | (CRC >> 8);
}
// ----------------------------------------------------------------------------

unsigned char *packed_ptr, *packed_end;

int readChar(void)
{
	if (packed_ptr < packed_end) return *packed_ptr++;
	else return -1;
}

// ------------------------------------------------------ LZH unpacker

unsigned char d_code[256] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
	0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
	0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
	0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
	0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
	0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
	0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
	0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
	0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
	0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
	0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
	0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
	0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
	0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
};

unsigned char d_len[256] = {
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
};


const int N = 4096;     // buffer size
const int F = 60;       // lookahead buffer size
const int THRESHOLD = 2;
const int NIL = N;      // leaf of tree

unsigned char text_buf[N + F - 1];

const int N_CHAR = (256 - THRESHOLD + F);       // kinds of characters (character code = 0..N_CHAR-1)
const int T = (N_CHAR * 2 - 1);       // size of table
const int R = (T - 1);                  // position of root
const int MAX_FREQ = 0x8000;            // updates tree when the
										// root frequency comes to this value.

unsigned short freq[T + 1];        // frequency table

short prnt[T + N_CHAR]; // pointers to parent nodes, except for the
						// elements [T..T + N_CHAR - 1] which are used to get
						// the positions of leaves corresponding to the codes.
short son[T];           // pointers to child nodes (son[], son[] + 1)


int r;

unsigned getbuf;
unsigned char getlen;

int GetBit(void)      /* get one bit */
{
	int i;

	while (getlen <= 8)
	{
		if ((i = readChar()) == -1) i = 0;
		getbuf |= i << (8 - getlen);
		getlen += 8;
	}
	i = getbuf;
	getbuf <<= 1;
	getlen--;
	return ((i >> 15) & 1);
}

int GetByte(void)     /* get one byte */
{
	unsigned i;

	while (getlen <= 8)
	{
		if ((int)(i = readChar()) == -1) i = 0;
		getbuf |= i << (8 - getlen);
		getlen += 8;
	}
	i = getbuf;
	getbuf <<= 8;
	getlen -= 8;
	return (i >> 8) & 0xFF;
}

void StartHuff(void)
{
	int i, j;

	getbuf = 0, getlen = 0;
	for (i = 0; i < N_CHAR; i++) {
		freq[i] = 1;
		son[i] = i + T;
		prnt[i + T] = i;
	}
	i = 0; j = N_CHAR;
	while (j <= R) {
		freq[j] = freq[i] + freq[i + 1];
		son[j] = i;
		prnt[i] = prnt[i + 1] = j;
		i += 2; j++;
	}
	freq[T] = 0xffff;
	prnt[R] = 0;

	for (i = 0; i < N - F; i++) text_buf[i] = ' ';
	r = N - F;
}

/* reconstruction of tree */
void reconst(void)
{
	int i, j, k;
	int f, l;

	/* collect leaf nodes in the first half of the table */
	/* and replace the freq by (freq + 1) / 2. */
	j = 0;
	for (i = 0; i < T; i++)
	{
		if (son[i] >= T)
		{
			freq[j] = (freq[i] + 1) / 2;
			son[j] = son[i];
			j++;
		}
	}
	/* begin constructing tree by connecting sons */
	for (i = 0, j = N_CHAR; j < T; i += 2, j++)
	{
		k = i + 1;
		f = freq[j] = freq[i] + freq[k];
		for (k = j - 1; f < freq[k]; k--);
		k++;
		l = (j - k) * sizeof(*freq);
		memmove(&freq[k + 1], &freq[k], l);
		freq[k] = f;
		memmove(&son[k + 1], &son[k], l);
		son[k] = i;
	}
	/* connect prnt */
	for (i = 0; i < T; i++)
		if ((k = son[i]) >= T) prnt[k] = i;
		else prnt[k] = prnt[k + 1] = i;
}


/* increment frequency of given code by one, and update tree */

void update(int c)
{
	int i, j, k, l;

	if (freq[R] == MAX_FREQ) reconst();

	c = prnt[c + T];
	do {
		k = ++freq[c];

		/* if the order is disturbed, exchange nodes */
		if (k > freq[l = c + 1])
		{
			while (k > freq[++l]);
			l--;
			freq[c] = freq[l];
			freq[l] = k;

			i = son[c];
			prnt[i] = l;
			if (i < T) prnt[i + 1] = l;

			j = son[l];
			son[l] = i;

			prnt[j] = c;
			if (j < T) prnt[j + 1] = c;
			son[c] = j;

			c = l;
		}
	} while ((c = prnt[c]) != 0);  /* repeat up to root */
}

int DecodeChar(void)
{
	int c;

	c = son[R];

	/* travel from root to leaf, */
	/* choosing the smaller child node (son[]) if the read bit is 0, */
	/* the bigger (son[]+1} if 1 */
	while (c < T) c = son[c + GetBit()];
	c -= T;
	update(c);
	return c;
}

int DecodePosition(void)
{
	int i, j, c;

	/* recover upper 6 bits from table */
	i = GetByte();
	c = (int)d_code[i] << 6;
	j = d_len[i];
	/* read lower 6 bits verbatim */
	j -= 2;
	while (j--) i = (i << 1) + GetBit();
	return c | (i & 0x3f);
}

unsigned unpack_lzh(unsigned char *src, unsigned size, unsigned char *buf)
{
	packed_ptr = src;
	packed_end = src + size;
	int  i, j, k, c;
	unsigned count = 0;
	StartHuff();

	//  while (count < textsize)  // textsize - sizeof unpacked data
	while (packed_ptr < packed_end)
	{
		c = DecodeChar();
		if (c < 256)
		{
			*buf++ = c;
			text_buf[r++] = c;
			r &= (N - 1);
			count++;
		}
		else {
			i = (r - DecodePosition() - 1) & (N - 1);
			j = c - 255 + THRESHOLD;
			for (k = 0; k < j; k++)
			{
				c = text_buf[(i + k) & (N - 1)];
				*buf++ = c;
				text_buf[r++] = c;
				r &= (N - 1);
				count++;
			}
		}
	}
	return count;
}
//--------------------------------------------------------------------------

#define VOLUME_NUMBER 254

#define TRACKS 35
#define SECTORS 16
#define SECTOR_SIZE 256
#define DOS_TRACK_uint8_tS (SECTORS * SECTOR_SIZE)

#define RAW_TRACK_uint8_tS 0x1A00

static uint8_t *target; /* Where to write in the raw_track buffer */

#define write_byte(x) (*target++ = (x))

static uint8_t GCR_encoding_table[64] = {
  0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6,
  0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3,
  0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC,
  0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3,
  0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE,
  0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC,
  0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
  0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF };

int	Swap_Bit[4] = { 0, 2, 1, 3 }; /* swap lower 2 bits */
static uint8_t	GCR_buffer[256];
static uint8_t	GCR_buffer2[86];

/* physical sector no. to DOS 3.3 logical sector no. table */
static int	Logical_Sector[16] = {
  0x0, 0x7, 0xE, 0x6, 0xD, 0x5, 0xC, 0x4,
  0xB, 0x3, 0xA, 0x2, 0x9, 0x1, 0x8, 0xF };

static int	Logical_Sector_po[16] = {
  0x0, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8,
  0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0xF };

/*
 * write an FM encoded value, used in writing address fields
 */
static void FM_encode(uint8_t data)
{
	write_byte((data >> 1) | 0xAA);
	write_byte(data | 0xAA);
}

/*
 * Write 0xFF sync bytes
 */
static void write_sync(int length)
{
	while (length--) write_byte(0xFF);
}

static void write_address_field(int volume, int track, int sector)
{
	/*
	 * write address mark
	 */
	write_byte(0xD5);
	write_byte(0xAA);
	write_byte(0x96);

	/*
	 * write Volume, Track, Sector & Check-sum
	 */
	FM_encode(volume);
	FM_encode(track);
	FM_encode(sector);
	FM_encode(volume ^ track ^ sector);

	/*
	 * write epilogue
	 */
	write_byte(0xDE);
	write_byte(0xAA);
	write_byte(0xEB);
}

/*
 * 6-and-2 group encoding: the heart of the "nibblization" procedure
 */
static void encode62(uint8_t *page)
{
	int i, j;

	/* 86 * 3 = 258, so the first two byte are encoded twice */
	GCR_buffer2[0] = Swap_Bit[page[1] & 0x03];
	GCR_buffer2[1] = Swap_Bit[page[0] & 0x03];

	/* save higher 6 bits in GCR_buffer and lower 2 bits in GCR_buffer2 */
	for (i = 255, j = 2; i >= 0; i--, j = j == 85 ? 0 : j + 1) {
		GCR_buffer2[j] = (GCR_buffer2[j] << 2) | Swap_Bit[page[i] & 0x03];
		GCR_buffer[i] = page[i] >> 2;
	}

	/* clear off higher 2 bits of GCR_buffer2 set in the last call */
	for (i = 0; i < 86; i++)
		GCR_buffer2[i] &= 0x3f;
}

static void write_data_field(uint8_t *page)
{
	int	i;
	uint8_t	last, checksum;

	encode62(page);

	/* write prologue */
	write_byte(0xD5);
	write_byte(0xAA);
	write_byte(0xAD);

	/* write GCR encoded data */
	for (i = 0x55, last = 0; i >= 0; --i) {
		checksum = last ^ GCR_buffer2[i];
		write_byte(GCR_encoding_table[checksum]);
		last = GCR_buffer2[i];
	}
	for (i = 0; i < 256; ++i) {
		checksum = last ^ GCR_buffer[i];
		write_byte(GCR_encoding_table[checksum]);
		last = GCR_buffer[i];
	}

	/* write checksum and epilogue */
	write_byte(GCR_encoding_table[last]);
	write_byte(0xDE);
	write_byte(0xAA);
	write_byte(0xEB);
}

int dsk2nib(const char *name, fileTYPE *f)
{
	int len = strlen(name);
	int po = 0;

	if (len > 3 && !strcasecmp(name + len - 3, ".po"))
	{
		po = 1;
	}
	else if (!(len > 4 && !strcasecmp(name + len - 4, ".dsk")) && !(len > 3 && !strcasecmp(name + len - 3, ".do")))
	{
		return 0;
	}

	static uint8_t dos_track[SECTORS * SECTOR_SIZE]; // , pro_track[SECTORS * SECTOR_SIZE];
	static uint8_t raw_track[RAW_TRACK_uint8_tS];

	fileTYPE disk_file = {};

	if (!FileOpen(&disk_file, name))
	{
		printf("Unable to mount disk file \"%s\"\n", name);
		return 0;
	}

	if (!FileOpenEx(f, "vdsk", -1))
	{
		FileClose(&disk_file);
		printf("ERROR: fail to create vdsk\n");
		return 0;
	}

	/* Read, convert, and write each track */
	for (int track = 0; track < TRACKS; ++track)
	{
		if (FileReadAdv(&disk_file, dos_track, DOS_TRACK_uint8_tS) != DOS_TRACK_uint8_tS)
		{
			printf("Unexpected end of disk data\n");
			FileClose(&disk_file);
			FileClose(f);
			return 0;
		}

		target = raw_track;

		for (int sector = 0; sector < SECTORS; sector++)
		{
			int sec = po ? Logical_Sector_po[sector] : sector;

			write_sync(38);    /* Inter-sector gap */
			write_address_field(VOLUME_NUMBER, track, sector);
			write_sync(8);
			write_data_field(dos_track + Logical_Sector[sec] * SECTOR_SIZE);
		}

		/* Pad rest of buffer with sync bytes */
		while (target != &raw_track[RAW_TRACK_uint8_tS]) write_byte(0xff);

		if (FileWriteAdv(f, raw_track, RAW_TRACK_uint8_tS) != RAW_TRACK_uint8_tS)
		{
			printf("Error writing to vdsk file\n");
			FileClose(&disk_file);
			FileClose(f);
			return 0;
		}
	}

	FileClose(&disk_file);

	f->size = FileGetSize(f);
	FileSeekLBA(f, 0);
	printf("dsk2nib: vdsk size=%llu.\n", f->size);

	return 1;
}

//--------------------------------------------------------------------------
int x2trd(const char *name, fileTYPE *f)
{
	TDiskImage *img = new TDiskImage;
	img->Open(getFullPath(name), true);

	if (!FileOpenEx(f, "vdsk", -1))
	{
		delete img;
		printf("ERROR: fail to create vdsk\n");
		return 0;
	}

	img->writeTRD(f);
	delete(img);

	f->size = FileGetSize(f);
	FileSeekLBA(f, 0);
	printf("x2trd: vdsk size=%llu.\n", f->size);

	return 1;
}

int x2trd_ext_supp(const char *name)
{
	const char *ext = "";
	if (strlen(name) > 4) ext = name + strlen(name) - 4;
	return (!strcasecmp(ext, ".scl") || !strcasecmp(ext, ".fdi") || !strcasecmp(ext, ".udi"));
}
